Question

I have an application with a UITabBar. Every tab is a UINavigationController with several UIViewControllers inside. One of those View Controllers contains a UITableView, and I want to display a floating menu for deleting the long pressed UITableViewCell.

I am using UIMenuController but it's not displayed because the cell refuses to become first responder.

Here's my code:

    - (void)viewDidLoad
    {
        [super viewDidLoad];

        UILongPressGestureRecognizer *lpgr = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPress:)];
        lpgr.minimumPressDuration = 1.0; //second
        [table addGestureRecognizer:lpgr];

        [lpgr release];
    }

-(void)handleLongPress:(UILongPressGestureRecognizer *)gestureRecognizer {
    if (gestureRecognizer.state == UIGestureRecognizerStateBegan) {
        CGPoint p = [gestureRecognizer locationInView: table];

        NSIndexPath *indexPath = [table indexPathForRowAtPoint:p];
        if (indexPath != nil) {
            UITableViewCell* cell = [self tableView:table cellForRowAtIndexPath: indexPath];

            [cell becomeFirstResponder];
            UIMenuItem *delete = [[UIMenuItem alloc] initWithTitle:@"Delete" action:@selector(delete:)];

            UIMenuController *menu = [UIMenuController sharedMenuController];
            [menu setMenuItems:[NSArray arrayWithObjects:delete, nil]];
            [menu setTargetRect:cell.frame inView:cell.superview];
            [menu setMenuVisible:YES animated:YES];
        }
    }
}

On the UITableViewCell I have overriden the method:

-(BOOL) canBecomeFirstResponder {
    return YES;
}

Any ideas on why the cell is not becoming the first responder?

Thanks!

Was it helpful?

Solution

I think I fixed your code :-)

-(void)handleLongPress:(UILongPressGestureRecognizer *)gestureRecognizer {
    if (gestureRecognizer.state == UIGestureRecognizerStateBegan) {
        CGPoint p = [gestureRecognizer locationInView: self.tableView];
        NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:p];
        if (indexPath != nil) {

            [self becomeFirstResponder];
            UIMenuItem *delete = [[UIMenuItem alloc] initWithTitle:@"Delete" action:@selector(customDelete:)];

            UIMenuController *menu = [UIMenuController sharedMenuController];
            [menu setMenuItems:[NSArray arrayWithObjects:delete, nil]];
            [menu setTargetRect:[self.tableView rectForRowAtIndexPath:indexPath] inView:self.tableView];
            [menu setMenuVisible:YES animated:YES];
        }
    }
}

- (void)customDelete:(id)sender {
//
}

- (BOOL)canBecomeFirstResponder {
    return YES;
}

- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
    if (action == @selector(customDelete:) ){
        return YES;
    }
    return NO;
}

I did the following..

  1. [self becomeFirstResponder];
  2. [menu setTargetRect:[self.tableView rectForRowAtIndexPath:indexPath] inView:self.tableView];
  3. Added true for canPerformAction Not mostly needed if you have implemented the function

Please change the tableview and other things to your local reference variables :-)

Good read - http://www.intridea.com/blog/2010/12/22/developers-notes-for-uimenucontroller

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top