没有粘贴:canPerformAction:withSender 中的操作:

No paste: action in canPerformAction:withSender:

我试图强行隐藏 UITextField 上的粘贴气泡。 我的实现是从 UIResponderStandardEditActions 中指定禁止选择器的列表,将其存储在 UIResponder 类别的 AssociatedValue 中,如果在列表中找到操作,则过早退出类别的 canPerformAction:withSender:。这是一种非常诱人的方法,因为它可以控制项目中的任何 Responder。

问题是,当我点击 UITextField 内部时,没有 paste: 操作到达整个响应链的任何 canPerformAction:withSender: 方法。我在 UIResponder 上写了一个类别,然后在 canPerformAction:withSender: 那里混了,所以我可以确定:

- (BOOL)my_canPerformAction:(SEL)action withSender:(id)sender {
    NSString *string = NSStringFromSelector(action);
    BOOL prohibited = [self.prohibitedActions containsObject:string];

    if (prohibited) {
        return NO;
    }

    BOOL canPerform = [self my_canPerformAction:action withSender:sender];
    return canPerform;
}

我的层次结构的全部内容是:

 cut:
 copy:
 select:
 selectAll:
 delete:
 _promptForReplace:
 _transliterateChinese:
 _insertDrawing:
 _showTextStyleOptions:
 _lookup:
 _define:
 _define:
 _addShortcut:
 _accessibilitySpeak:
 _accessibilitySpeakLanguageSelection:
 _accessibilityPauseSpeaking:
 _share:
 makeTextWritingDirectionLeftToRight:

禁止_promptForReplace:没有帮助。另外,我的 TextField 没有实现 canPerformAction:withSender:.

那么,我应该怎么做才能找到并隐藏那个令人讨厌的粘贴?

所以在swift我会这样做:

UIMenuController.shared.menuItems?.removeAll(where: {[=10=].title == "paste"})

在 objective-c 中,您可以尝试这样的操作:

 UIMenuController * controller = [UIMenuController sharedMenuController];
     NSArray * items = [controller menuItems]; // These are all custom items you added
     NSMutableArray * finalItemsYouWant = [NSMutableArray array];
     // Here you can check what items you don't want and then remove it
     [controller setMenuItems:finalItemsYouWant];

所以试着找出所有的菜单项并强行删除你想要的那个

UITextField 而不是 UIResponder 上创建类别成功了。 子类化 UITextField 和实现 canPerformAction:withSender: 都可以。

事实证明,UIResponder 上的类别不会影响 UITextField 上的 canPerformAction:withSender:,即使 UITextField IS-A UIResponder。我不知道这是 iOS 中的一个错误还是它的内部行为有些奇怪。

我的错是太依赖调配了。我不建议您使用这种 "universal" 方法,例如创建一个包含 "prohibited" 操作选择器列表的类别以与任何响应者一起使用。