7
votes

Tapping the cursor in a UITextView brings up a UIMenuController. Tapping Select causes the relevant text to be selected and another UIMenuController with new options to be displayed. Tapping anywhere else in the text view causes the "second" UIMenuController to hide.

Example of system behavior

I have a custom UIMenuItem that, when tapped, selects the current line of text in a UITextView and then displays the UIMenuController again for subsequent actions, however the "second" UIMenuController does not hide when tapping anywhere else in the view as expected.

Example of undesired behavior

Custom menu item action:

- (void)selectLine:(id)sender {
    NSString *string = [[self textView] text];
    NSRange range = [[self textView] selectedRange];
    NSRange newRange = [string lineRangeForRange:range];

    if ([[string substringWithRange:newRange] hasSuffix:@"\n"]) {
        newRange.length -= 1;
    }
    [[self textView] setSelectedRange:newRange];

    CGRect targetRect = [[self textView] firstRectForRange:[[self textView] selectedTextRange]];
    UIMenuController *menuController = [UIMenuController sharedMenuController];
    [menuController setTargetRect:targetRect inView:[self textView]];
    [menuController setMenuVisible:YES animated:YES];
}
1
Try putting in a delay before the last three lines. Give the current menu a chance to tear down.matt
Tried a 2 second delay. Didn't make a difference.CyberMoai
How do you customize that second menu after the text is selected? I want to have my own text formatting options only after the text is selected.Clifton Labrum
@CliftonLabrum UIMenuController is a shared/singleton object, so technically there can only be one. Menu items can be toggled via the canPerformAction:withSender: method. I check the selectedRange property of UITextView to determine if I should show my custom menu item.CyberMoai

1 Answers

2
votes

You can hide the UIMenuController on changing selection of your UITextView:

@interface ViewController () <UITextViewDelegate>
@property (weak, nonatomic) IBOutlet UITextView *textView;
@end

@implementation ViewController
@synthesize textView;

- (void)viewDidLoad {
    [super viewDidLoad];
    textView.delegate = self;
}

- (void)selectLine:(id)sender {
    ...
}

#pragma mark - UITextViewDelegate

- (void)textViewDidChangeSelection:(UITextView *)textView {
    if (UIMenuController.sharedMenuController.isMenuVisible) {
        [UIMenuController.sharedMenuController setMenuVisible:NO animated:YES];
    }
}