简体   繁体   English

iOS:弹出菜单的行为与第一响应者设置不符

[英]iOS: Pop-up menu does not behave in accordance with first responder set

I have several objects inheriting UIView in my application that are tracking taps on them and presenting Copy/Paste pop-up if they contain some specific data. 我有几个在我的应用程序中继承UIView对象,它们跟踪它们上的点击并显示复制/粘贴弹出窗口,如果它们包含一些特定数据。 When pop-up is presented I change the appearance of the object as well. 当弹出窗口时,我也改变了对象的外观。

This is how it is implemented: 这是它的实现方式:

- (void)viewDidReceiveSingleTap:(NSNotification *)n {
    MyObject *mo = (MyObject *)n.object;

    [mo becomeFirstResponder];
    UIMenuController *menu = [UIMenuController sharedMenuController];
    [menu update];

    [menu setTargetRect:CGRectMake(...) inView:mo];

    [menu setMenuVisible:YES animated:YES];
}

MyObject class, in turn, defines canBecomeFirstResponder: and canResignFirstResponder: as always returning YES . 反过来, MyObject类定义了canBecomeFirstResponder:canResignFirstResponder:总是返回YES becomeFirstResponder: , resignFirstResponder: , and canPerformAction:withSender: is also defined accordingly (this is where I change the appearance of the object). becomeFirstResponder: , resignFirstResponder: ,和canPerformAction:withSender:也相应地定义(这是我改变对象外观的地方)。

This is what goes wrong: 这是出了什么问题:

I tap object 1. The method viewDidReceiveSingleTap: above is getting called, and the object's canBecomeFirstResponder: and becomeFirstResponder: are getting called too. 我点击对象1.方法viewDidReceiveSingleTap:上面被调用,对象的canBecomeFirstResponder:becomeFirstResponder:也被调用了。 The pop-up menu is displayed as expected. 弹出菜单按预期显示。

I tap another object 2. viewDidReceiveSingleTap: is called again and here's where the trouble starts. 我点击另一个对象2. viewDidReceiveSingleTap:再次被调用,这里是麻烦开始的地方。 First, canResignFirstResponder: , resignFirstResponder: of object 1 are called, but not always, and I can't figure out the pattern. 首先, canResignFirstResponder:对象1的canResignFirstResponder:resignFirstResponder:但不总是,我无法弄清楚模式。 canBecomeFirstResponder: and becomeFirstResponder: of object 2 are called properly, but the pop-up menu does not relocate. canBecomeFirstResponder:becomeFirstResponder:正确调用对象2,但弹出菜单不重定位。 It just disappears (though in the viewDidReceiveSingleTap: I clearly call setMenuVisible:YES ). 它只是消失了(虽然在viewDidReceiveSingleTap:我明确地调用setMenuVisible:YES )。 In order to make it appear, I have to tap object 2 (or any other) again -- in this case I can see from the debugger that object 2 was set as a first responder, it's just the pop-up that wasn't appearing. 为了使它出现,我必须再次点击对象2(或任何其他) - 在这种情况下,我可以从调试器看到对象2被设置为第一响应者,它只是弹出窗口不是出现。

What am I doing wrong? 我究竟做错了什么? Any clues on relation between pop-up menu visibility and first responder? 关于弹出菜单可见性和第一响应者之间关系的任何线索?

The issue is that, when you tap anywhere except on the menu, it does an animated hide of itself. 问题是,当你点击菜单上的任何地方时,它会自动隐藏动画。 That hide is taking precedence over your animated show. 隐藏优先于你的动画节目。 So, if you tap a view to make the menu show, tap anywhere else (either on another one of those views or just anywhere else), and then tap another one of those views, the menu will show every time. 因此,如果您点按视图以显示菜单,请点击其他任何地方(在其他任何一个视图或其他任何地方),然后点按其中一个视图,菜单将每次显示。

I think there's a good argument to be made for keeping that behavior, because it's the standard behavior that users will expect. 我认为保持这种行为是一个很好的论据,因为它是用户期望的标准行为。 But, of course, you have a better idea of what makes sense for your app. 但是,当然,您可以更好地了解对您的应用程序有意义的内容。 So, here's the trick: 所以,这是诀窍:

[menu setMenuVisible:NO animated:NO];
[menu setMenuVisible:YES animated:YES];

Here's the code I used to try it out: 这是我用来试用的代码:

@implementation MenuView

- (id)initWithFrame:(CGRect)frame {

    self = [super initWithFrame:frame];
    if (self) {
        self.backgroundColor = [UIColor blueColor];
    }
    return self;
}


- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    [self becomeFirstResponder];
    UIMenuController *menu = [UIMenuController sharedMenuController];
    UIMenuItem *item = [UIMenuItem alloc] initWithTitle:@"Test"
                                                 action:@selector(test)];
    NSArray *items = [NSArray arrayWithObject:item];
    [item release];
    [menu setMenuItems:items];

    [menu setTargetRect:self.bounds inView:self];

    [menu setMenuVisible:NO animated:NO];
    [menu setMenuVisible:YES animated:YES];
}

- (void)test {
    NSLog(@"Test!");
}

- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
    return action == @selector(test);
}

- (BOOL)canBecomeFirstResponder {
    NSLog(@"Can become called");
    return YES;
}

- (BOOL)canResignFirstResponder {
    NSLog(@"Can resign called");
    return YES;
}

- (BOOL)becomeFirstResponder {
    [super becomeFirstResponder];
    NSLog(@"Become called");

    return YES;
}

- (void)dealloc {
    [super dealloc];
}


@end

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM