1

I simply want to display the UIMenuController right after a textfield has become active.
What i'm doing right now is:

- (IBAction)textFieldeditingDidBegin:(UITextField *)sender {
    // textfield menu item
    UIMenuController *menu = [UIMenuController sharedMenuController];
    [menu setTargetRect:sender.frame inView:self.view];
    [menu setMenuVisible:YES animated:YES];
}

The method gets called but it just will not display the menu...
If i do a touch+hold gesture on the textfield it comes up regularly.

I hope there's a simple solution for that, Thanks

yinkou
  • 5,756
  • 2
  • 24
  • 40

2 Answers2

8

I found a good solution to your question.

You can easily make the UIMenuController appear when you start editing your text field with this method:

- (void)textFieldDidBeginEditing:(UITextField *)textField
{
    double delayInSeconds = 0.1;
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC);
    dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
        UIMenuController *menu = [UIMenuController sharedMenuController];
        [menu setTargetRect:textField.frame inView:textField.superview];
        [menu setMenuItems:[NSArray arrayWithObjects:
                            [[UIMenuItem alloc] initWithTitle:@"Test" action:@selector(test)],
                            nil]];
        [menu setMenuVisible:YES animated:YES];
    });
}

I use the dispatch_after call to make sure that the menu is show after all the defaults system calls on the UITextField are completed.

I also changed the inView:self.view part of the setTargetRect:: method with inView:textField.superview to be sure the menu is showing correctly in the container view of the text field.

If you also want to disable the default menu controls for a UITextField you can add this method to your controller:

- (BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
    if (action == @selector(cut:))
        return NO;
    else if (action == @selector(copy:))
        return NO;
    else if (action == @selector(paste:))
        return NO;
    else if (action == @selector(select:) || action == @selector(selectAll:))
        return NO;
    else
        return [super canPerformAction:action withSender:sender];
}

This work really well in the simulator. I hope this will help you!

marzapower
  • 5,531
  • 7
  • 38
  • 76
  • "While the default controls for a UITextField are available, every customization of the UIMenuController will not work. By explicitly disabling them, you can display whatever you want in your menu controller." -> Wrong, it works. I need them so i won't implement your first part. But the second thing sounds good, i'll try it today. – yinkou Jul 09 '12 at 13:35
  • 1
    @yinkou, I am sorry but there was a typo in my test application source code. You are right, you can have both controls at the same time. The main method is working correctly :) I updated the answer to reflect these changes. – marzapower Jul 09 '12 at 14:12
2

A simpler solution:

- (void)textFieldDidBeginEditing:(UITextField *)textField
{
    [[NSOperationQueue mainQueue] addOperationWithBlock:^{
        [textField select:nil];
        UIMenuController *menuController = [UIMenuController sharedMenuController];
        [menuController setMenuVisible:YES animated:YES];
    }];
}
Rudolf Adamkovič
  • 31,030
  • 13
  • 103
  • 118