简体   繁体   English

从UIMenuController中删除复制,查找和共享

[英]Removing Copy, Look Up, and Share from UIMenuController

I am trying to override the default UIMenuController so that only my custom item "Define..." appears when the user selects text in its text view. 我试图覆盖默认的UIMenuController以便当用户在其文本视图中选择文本时,只显示我的自定义项“定义...”。 I haven't had much luck with the approaches I've found online thus far. 到目前为止,我在网上找到的方法并没有太多运气。

To be more specific, I have subclassed a UIViewController and used canPerformAction() to exclude all actions except my define method. 更具体地说,我已经将UIViewController子类化,并使用canPerformAction()来排除除了我的define方法之外的所有动作。

override func becomeFirstResponder() -> Bool {
    return true
}

override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
    let canPerform: Bool
    if action == #selector(defineWord){
        canPerform = true
    }
    else {
        canPerform = false
    }

    print("action = \(action), canPerform = \(canPerform)")
    return canPerform
}

In the view controller's viewDidLoad() , I've included the following: 在视图控制器的viewDidLoad() ,我包括以下内容:

let shared = UIMenuController.shared
let menuItemDefine = UIMenuItem(title: "Define...", action: #selector(self.defineWord))
shared.menuItems = [menuItemDefine]

Whenever I select text in the view, the console goes through each possible action that might appear in the UIMenuController and says they can't be performed, with the exception of my custom action: 每当我在视图中选择文本时,控制台都会检查可能出现在UIMenuController中的每个可能的操作,并表示无法执行这些操作,但我的自定义操作除外:

action = cut:, canPerform = false
action = select:, canPerform = false
(and so on, until...)
action = defineWord, canPerform = true

But the resulting edit menu contains "Copy", "Look Up", "Share", and "Define...". 但生成的编辑菜单包含“复制”,“查找”,“共享”和“定义...”。 These don't appear in the console, which makes me think that a different approach is called for. 这些不会出现在控制台中,这让我觉得需要采用不同的方法。

Note that I've also tried subclassing UITextView and using the above code as appropriate, but the result is the same. 请注意,我还尝试了子类化UITextView并根据需要使用上面的代码,但结果是一样的。

Any ideas where I'm going wrong? 我出错的任何想法?

This might help everyone who is asking this question that how to remove "Copy", "Select All" etc.. standard menu items or UIResponderStandardEditActions that are still visible when you have already returned false in canPerformAction: . 这可能有助于所有提出此问题的人如何删除“复制”,“全选”等等。标准菜单项或UIResponderStandardEditActionscanPerformAction:已经返回false时仍然可见canPerformAction:

It is related to responder chain. 它与响应者链有关。 As canPerformAction: is called for every responder, for some of those it may be returning true in canPerformAction: as a default value. 因为canPerformAction:为每个响应者调用,对于其中一些响应者,它可能在canPerformAction:返回true canPerformAction:作为默认值。

Thus to check where it is failing I found it by overriding this canPerformAction: for every element I used in my controller 因此,为了检查它失败的地方,我通过覆盖这个canPerformAction:找到它canPerformAction:对于我在控制器中使用的每个元素

For example in my view controller I had a webview and the mistake I was doing was that I was overriding the canPerformAction: in the delegate methods ie I was doing something like below 例如,在我的视图控制器中,我有一个webview ,我正在做的错误是我重写了canPerformAction:在委托方法中,即我正在做类似下面的事情

extension viewcontroller: UIWebViewDelegate{
    open override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
        return false
    }
}

But the point is that you have to do it for element and not as the delegate method. 但重点是你必须为元素而不是委托方法。

extension UIView {

    func dropRoundCorners() {
        self.layer.cornerRadius = 10.0;
        self.clipsToBounds = true;
    }

    open override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
        return false
    }
}

extension UIImageView{
    open override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
        return false
    }
}

extension UIScrollView{
    open override func canPerformAction(_ action: Selector, withSender 
sender: Any?) -> Bool {
        return false
    }
}

extension UISlider{
    open override func canPerformAction(_ action: Selector, withSender 
sender: Any?) -> Bool {
        return false
    }
}

extension UIWebView{
   open override func canPerformAction(_ action: Selector, withSender 
sender: Any?) -> Bool {
        return false
    }
}

I hope this is useful to anyone whose is stuck with this issue. 我希望这对任何坚持这个问题的人都有用。

Following are links that might help you with details: 以下链接可能会帮助您了解详细信息:

UIResponder reference UIResponder参考

very important read the discussion here regarding responder 非常重要的是阅读有关响应者的讨论

some what related 一些相关的东西

May be it is too late for the answer, but it can be helpful for other users. 对于答案可能为时已晚,但对其他用户可能会有所帮助。 So, my solution is: I created custom UITextView and redefined the following methods: 所以,我的解决方案是:我创建了自定义UITextView并重新定义了以下方法:

- (BOOL)canBecomeFirstResponder {
    return YES;
}

- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
    //Here you can check for all action what you need
    return (action == @selector(yourCustomAction)) ? YES : NO;
}

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

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