2

I am trying to execute an IBAction when a long-press is performed on a cell in a UITableView. The action involves the content of the cell so I need to get the indexPath in order to retrieve the content from a dictionary in local storage. The IBAction method is defined in the MasterViewController.m file which contains the UITableView methods and is subclassed from UITableViewController. I have tried all of the following, and they all return null instead of the indexPath for the cell.

UITableViewCell *cell = (UITableViewCell *)self;
NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];

NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];

NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];

I have also seen a few years-old answers to similar questions that use the position of the cell in the view, but I can't get any of those to work either.

UPDATE: The IBAction, sendToPB, is being defined in a subclass of UITableViewController. There is a long-press gesture recognizer added to the cell in Interface Builder, with Sent Actions connected to sendToPB. The action is supposed to be copying the content of the cell to the clipboard when you long-press on the cell in the table view. All the ways I have tried so far return null for indexPath.

- (IBAction)sendToPB:(id)sender {
    NSIndexPath *indexPath = [self.tableView indexPathForCell:sender];
    NSString *object = self.objects[indexPath.row];
    UIPasteboard *pb = [UIPasteboard generalPasteboard];
    NSString *pressedCellText = [[Data getAllNotes] objectForKey:object];
    [pb setString: pressedCellText];
}

UPDATE: I have found two problems with this approach. First, the long-press gesture doesn't actually select the row, which is why all of the options that used indexPathForSelectedRow don't work. Second, sender is the gesture recognizer, and not the cell or row, so using sender also produces a null value for indexPath. With these two factors in mind, how else can you detect which cell you performed the long-press on?

ChiliOcean
  • 61
  • 1
  • 6
  • 1
    when you debug, what type of object does self seem to be? You cast it as a table cell but then you also call self.tableView like it's a view controller. – valheru Nov 04 '14 at 04:02
  • Add the code snippet for add the long gestures to the cell – Ramesh Muthe Nov 04 '14 at 04:17
  • You need to show more code. Show how the long press is setup and handled. – rmaddy Nov 04 '14 at 04:53
  • Please see my answer below and try NSIndexPath *indexPath = self.tableview.indexPathForSelectedRow Then breakpoint and report the values of indexPath and object. – Khaled Barazi Nov 04 '14 at 05:32
  • @Spectravideo328 indexPath is null, and object is 2014-11-02 13:24:38 +0000 (the key of the first cell in the table). So no matter which cell you press on, because indexPath is null, you always get the content of the first cell, row 0, sent to the clipboard. – ChiliOcean Nov 04 '14 at 05:52
  • @ChiliOcean You still haven't told us what `sender` is in your `sendToPB:` method. It's probably not the cell. – rmaddy Nov 04 '14 at 06:03
  • @rmaddy The gesture recognizer is attached to the cell, so doesn't that make the cell the sender? – ChiliOcean Nov 04 '14 at 06:35
  • 1
    @ChiliOcean No, it probably makes the gesture recognizer the sender. Why don't you check using the debugger. – rmaddy Nov 04 '14 at 06:41
  • @maddy You were correct that sender is the gesture recognizer. – ChiliOcean Nov 05 '14 at 03:13
  • @ChiliOcean you can get cell from gesture recognisers view property like this `UITableViewCell *cell=(UITableViewCell*)recogniser.view ` and you can then get index path easily – Pratik Jamariya Dec 13 '16 at 12:19

7 Answers7

2

Declare variable 1st in .h file as

 NSIndexPath *hitIndex;

then on long press method u can get the position of cell & hence indexpath

(void)longPressMethod:(UIButton *)btn
{

CGPoint hitPoint = [btn convertPoint:CGPointZero toView:tbl_traits];
hitIndex = [tbl_traits indexPathForRowAtPoint:hitPoint];

}
Luca D'Alberti
  • 4,749
  • 3
  • 25
  • 45
poojathorat
  • 1,200
  • 2
  • 9
  • 19
  • What is `tbl_traits`? Why does `hitIndex` need to an ivar? And which .h file do you mean? – rmaddy Nov 04 '14 at 04:55
  • tbl_trait is the object of tableview & hitIndex is the NSIndexPath object so that u can get the contents of cell using hitIndex.row & .h is the simple controllers .h file to declare varible. – poojathorat Nov 04 '14 at 05:04
  • Where in the OP's question is there a mention of `tbl_traits` and a "simple controller"? Your answer is confusing and out of context. – rmaddy Nov 04 '14 at 05:10
  • simple controller is just the controller in which u have added tableview & tbl_trait is the object of tableview for which longpress gesture method will be there,u can add this method as follow: UILongPressGestureRecognizer *lpgr = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressMethod:)]; lpgr.minimumPressDuration = 2.0; //seconds lpgr.delegate = self; [self. tbl_traits addGestureRecognizer:lpgr]; [lpgr release]; – poojathorat Nov 04 '14 at 05:22
2

You can get indexPath Like This on longPressGesture!

-(void)handleLongPress:(UILongPressGestureRecognizer *)gestureRecognizer
{
     CGPoint p = [gestureRecognizer locationInView:self.myTableView];

     NSIndexPath *indexPath = [self.myTableView indexPathForRowAtPoint:p];
     if (indexPath == nil) {
         NSLog(@"long press on table view but not on a row");
     } 
     else if (gestureRecognizer.state == UIGestureRecognizerStateBegan) 
     {

         NSLog(@"long press on table view at row %d", indexPath.row);
     } 
     else 
     {
         NSLog(@"gestureRecognizer.state = %d", gestureRecognizer.state);
     }
}

may Be this Link will help you a little more

Community
  • 1
  • 1
Saurabh Prajapati
  • 2,348
  • 1
  • 24
  • 42
1

You can do it using Gesture Recognizers. Hope these snippets help.......

In your .h file

@interface yourClass ()
{
    UILongPressGestureRecognizer *longPressRecognizer;
}

In viewDidLoad,

longPressRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(longPressDetected:)];
longPressRecognizer.minimumPressDuration = 2;
longPressRecognizer.numberOfTouchesRequired = 1;
longPressRecognizer.delegate = self;

In cellForRowAtIndexPath, just before return statement

[cell addGestureRecognizer:longPressRecognizer];

And at the end,

- (void) longPressDetected:(UILongPressGestureRecognizer *)recognizer 
{
    UITableViewCell *selectedCell = (UITableViewCell *)recognizer.view;
    // Your required code here
}
P.J.Radadiya
  • 1,493
  • 1
  • 12
  • 21
Akshay Bhalotia
  • 799
  • 4
  • 11
0

Edit: Thanks to @RegularExpression

First be sure to set the delegate of your tableView

self.myTableView.delegate = self

I believe this is what you are looking for:

Swift

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    //save the indexPath.row as an integer inside a property or pass it to your action
}

You can then save the index of from the above method or simple call your action passing that index inside the above method.

Objective-C

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{

       //save the indexPath.row as an integer inside a property or pass it to your action
}
Siavash Alp
  • 1,412
  • 15
  • 14
0

If this is inside a UITableViewController subclass, then casting self (which is an instance of the UITableViewController subclass) to UITableViewCell will not return the cell selected.

There is really 2 ways of doing this:

1- The easy way: Don't use an IBAction and just implement the delegate methods:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

2- The relatively easy way: in your IBaction, you can get the selected cell by using the property:

self.tableview.indexPathForSelectedRow

This property will give you the indexpath of the selected cell.

Khaled Barazi
  • 8,681
  • 6
  • 42
  • 62
  • The user wants to detect long press. Sorry dude, -1 for this. – Akshay Bhalotia Nov 04 '14 at 05:12
  • @LibranCoder I think you are confused on the rules of downvoting. I suggest your review them. The OP's question is how to determine the cell that was selected and not how to create the long press gesture recognizer. – Khaled Barazi Nov 04 '14 at 05:20
  • I'm sorry for the misunderstanding. – Akshay Bhalotia Nov 04 '14 at 05:54
  • @librancoder is right, the question is about detecting which cell was long-pressed, not which is the selected cell. and there's nothing wrong with down voting other answers to questions you're answering! If you read a question, see an answer you think is wrong and have an answer you think is right, why wouldn't you downvote? – jrturton Nov 04 '14 at 07:07
  • @LibranCoder I think if we allow downvoting in the interest of self-promotion (or not) to propagate, the SO community will not be able to tell the difference between a downvoted answer based on the quality versus self promotion. My 2 cents... – Khaled Barazi Nov 04 '14 at 09:36
0

If you attached the UILongPressGestureRecognizer to the cell by calling cell.addGestureRegognizer(_: _: _:) you should retrieve the cell from the sender by doing

let touchedView = sender.view as! UITableViewCell

Anyway, the best way to achieve this usually is by inspecting the dataSource instead of calling the UITableViewDataSource methods

Luca D'Alberti
  • 4,749
  • 3
  • 25
  • 45
-1

You could subclass UITableViewCell and add an IVar for the index path and set that when cellForRowAtIndexPath is called for the UITableView dataSource protocol.

Nick Wilkerson
  • 353
  • 2
  • 17