Removing Copy, Look Up, and Share from UIMenuController

旧时模样 提交于 2019-12-11 03:25:57

问题


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. 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.

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:

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:

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.

Any ideas where I'm going wrong?


回答1:


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:.

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.

Thus to check where it is failing I found it by overriding this canPerformAction: for every element I used in my controller

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 i.e I was doing something like below

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

very important read the discussion here regarding responder

some what related




回答2:


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:

- (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;
}


来源:https://stackoverflow.com/questions/39885345/removing-copy-look-up-and-share-from-uimenucontroller

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!