Search code examples
objective-cioscocoa-touchuitextfielduimenucontroller

Display UIMenuController in editingDidBegin of a UITextField


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


Solution

  • 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!