Cannot Disable Default UIMenuItems in UIMenuContro

2019-08-26 20:46发布

问题:

I'm trying to configure UIMenuController's menu items for a functionality similar to Medium's iOS feature:

There are a variety of threads devoted to this specific task, but despite tens of thousands of views and varied results, including it not working for a significant enough number of people... it doesn't seem like there is a solution that works consistently for UITextView.

I have been able to add a custom menu option "printToConsole", but I can't disable Apple's standard menu items like cut, copy, paste, B I U, etc:

The consensus seems to be that I should override canPerformAction to disable these default menu items as such, but that doesn't seem to be working:

override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
    print("canPerformAction being called")

    if action == #selector(cut(_:)) {
        return false
    }
    if action == #selector(copy(_:)) {
        return false
    }
    if action == #selector(select(_:)) {
        return false
    }
    if action == #selector(paste(_:)) {
        return false
    }
    if action == #selector(replacementObject(for:)) {
        return false
    }
    if action == #selector(selectAll(_:)) {
        return false
    }
    if action == #selector(printToConsole) {
        return true
    }

    return super.canPerformAction(action, withSender: sender)
}

This is the remainder of my relevant code:

func addCustomMenu() {
    let consolePrintAction = UIMenuItem(title: "Print To Console", action: #selector(printToConsole))
    UIMenuController.shared.menuItems = [consolePrintAction]
    UIMenuController.shared.update()

}

@objc func printToConsole() {
    if let range = articleTextView.selectedTextRange, let selectedText = articleTextView.text(in: range) {
        print(selectedText)
    }
}

And in my viewDidLoad:

articleTextView.delegate = self
addCustomMenu()

I've set my viewController to conform to UITextViewDelegate as well. Some are suggesting that if you simply subclass the TextView this will work somehow. I haven't been able to get that to work, so if that is truly the answer, can someone provide an example?

Again, I know this may seem like a duplicate, but the above solution appears to have stopped working with an update of iOS.

Thanks.

回答1:

Going to give credit to @gaurav for his answer on this one, which must have escaped me in my hunt on SO: https://stackoverflow.com/a/46470592/7134142

The key piece of code is this, which is extending UITextView, rather than subclassing it:

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

Overriding canPerformAction in my view controller was unnecessary, and the above code still allows you to add your custom menu items. This is what I ended up with: