views:

486

answers:

1

I'm working on a navigation-based iPhone-only app that serves two main purposes: One, to present data in a hierarchical view, allowing users to drill down and eventually edit said data, and, two, to all users to perform a default action when the table view cell is tapped. I now need to offer a small set of options tied to the same data; however, both the didSelectRowAtIndexPath: and accessoryButtonTappedForRowAtIndexPath: methods are obviously taken.

So, my options seem to be to implement a double-tap method, wherein the small list of additional options would be presented after (you guessed it) a double-tap on said table row; or, preferably, a tap-and-hold method. From what I can tell, tap-and-hold seems like the way to go in SDK 4.0 - which does me no good right this red-hot minute. I decided to go with the double-tap option, but I'm having a little trouble.

First and foremost, the touchesBegan:withEvent: method does not seem to be getting called at all; a breakpoint placed within the method is never called while the application runs, and the table view responds exactly as it did before I inserted the method (which is to say, it performs the default action):

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    UITouch *aTouch = [touches anyObject];
    if (aTouch.tapCount == 2) {
        [NSObject cancelPreviousPerformRequestsWithTarget:self];
    }
}

Second, I don't really need to handle a single-tap - the didSelectRowAtIndexPath: method can handle the single-tap just fine. The double-tap is the funky one I want to handle. I suspect the answer is going to contain the phrase, "You can't have the table view handle the single-tap and the touchesBegan: method handle the double-tap. The touch handling methods have to handle all of them."

I would really appreciate some guidance from some of you who've dealt with this issue. Thanks in advance.

+2  A: 

Okay, after a week of head-scratching and mumbling under my breath, I've finally come to the following conclusion: While what I want to do might theoretically be possible using the current version of iPhone OS, the effort to make it work is going to be Herculean in scale. Seeing as how iPhone OS 4 is due out in the near future, I have elected to use a 4.0 SDK feature to implement the behavior I'm looking for.

Specifically, what I have done is this:

// in my tableView:cellForRowAtIndexPath: method
static NSString *CellIdentifier = @"CustomCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
[[NSBundle mainBundle] loadNibNamed:@"TableViewCell" owner:self options:nil];
    cell = tvCell;
    self.tvCell = nil;
}
UILabel *label;
label = (UILabel*)[cell viewWithTag:1];
label.text = [NSString stringWithFormat:@"Main Label"];
label = (UILabel*)[cell viewWithTag:2];
label.text = [NSString stringWithFormat:@"Sub Label"];
UILongPressGestureRecognizer *recognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPress:)];
[[cell viewWithTag:0] addGestureRecognizer:recognizer];
[recognizer release];
UIImage *theImage = [UIImage imageNamed:@"silhouette.png"];
UIImageView *pictureView = (UIImageView*)[cell viewWithTag:0];
pictureView.image = theImage;
return cell;

I created a separate NIB file for the custom cell; it's just a tableViewCell object with an imageView (for a contact's photo) on the far left, and two labels in the center (a main label with larger text and a sub-label with smaller text). The cellForRowAtIndexPath: method loads this custom cell as necessary, and then populates the cell with some static data (this will obviously be changed when I incorporate this code into my existing app). I only had to implement one new method for the gesture recognizer:

- (void)handleLongPress:(UILongPressGestureRecognizer*)sender {
NSLog(@"Long press detected.");
}

Obviously, this, too, will be fleshed out when I actually put it to use.

The whole deal works like a charm. Tapping and holding on the cell fires the "Long press detected" log, and a regular single-tap fires a similar "Short press detected" log in the tableView:didSelectRowAtIndexPath: method.

Hope this helps somebody.

Andy