UIMenuItem #selector method crash in wkwebview

笑着哭i 提交于 2019-12-23 15:24:07

问题


UIMenuItem selector method crashes in iOS 11 beta SDK.

-[WKContentView highlightText]: unrecognized selector sent to instance 0x7f85df8f3200

Method Definition:

func highlightText() 
{
  //
}

I try to add UIMenuItem in WKWebView,

let menuItemHighlight = UIMenuItem.init(title: "Highlight", action: #selector(ContentWebkitView.highlightText))
UIMenuController.shared.menuItems = [menuItemHighlight]

回答1:


I was also getting this error when I was overriding canPerformAction and checking for my custom selector. In my case I wanted to remove all menu items except for my custom one and the following made this work for me.

class ViewController: UIViewController {

    @IBOutlet weak var webView: MyWebView!

    override func viewDidLoad() {
        super.viewDidLoad()

        loadWebView()
        setupCustomMenu()
    }

    func loadWebView() {
        let url = URL(string: "http://www.google.com")
        let request = URLRequest(url: url!)
        webView.load(request)
    }

    func setupCustomMenu() {
        let customMenuItem = UIMenuItem(title: "Foo", action:
            #selector(ViewController.customMenuTapped))
        UIMenuController.shared.menuItems = [customMenuItem]
        UIMenuController.shared.update()
    }

    @objc func customMenuTapped() {
        let yay = "🤪🤪🤪🤪🤪🤪🤪🤪🤪🤪🤪🤪"
        let alertView = UIAlertController(title: "Yay!!", message: yay, preferredStyle: .alert)
        alertView.addAction(UIAlertAction(title: "cool", style: .default, handler: nil))
        present(alertView, animated: true, completion: nil)
    }
}

class MyWebView: WKWebView {
    // turn off all other menu items
    override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
        return false
    }
}



回答2:


OK, we finally made it work for Swift 4:

  1. In your WKWebView subclass, add the following property and method:

    // MARK: - Swizzling to avoid responder chain crash    
    var wkContentView: UIView? {
        return self.subviewWithClassName("WKContentView")
    }
    
    
    private func swizzleResponderChainAction() {
        wkContentView?.swizzlePerformAction()
    }
    
  2. Then, add an extension to UIView (I put it in the same file as my WKWebView subclass, you can make it fileprivate if you'd like)

    // MARK: - Extension used for the swizzling part linked to wkContentView 
    extension UIView {
    
        /// Find a subview corresponding to the className parameter, recursively.
        func subviewWithClassName(_ className: String) -> UIView? {
    
            if NSStringFromClass(type(of: self)) == className {
                return self
            } else {
                for subview in subviews {
                    return subview.subviewWithClassName(className)
                }
            }
            return nil
        }
    
        func swizzlePerformAction() {
            swizzleMethod(#selector(canPerformAction), withSelector: #selector(swizzledCanPerformAction))
        }
    
        private func swizzleMethod(_ currentSelector: Selector, withSelector newSelector: Selector) {
            if let currentMethod = self.instanceMethod(for: currentSelector),
                let newMethod = self.instanceMethod(for:newSelector) {
                let newImplementation = method_getImplementation(newMethod)
                method_setImplementation(currentMethod, newImplementation)
            } else {
                print("Could not find originalSelector")
            }
        }
    
        private func instanceMethod(for selector: Selector) -> Method? {
            let classType = type(of: self)
            return class_getInstanceMethod(classType, selector)
        }
    
        @objc private func swizzledCanPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
            return false
        }
    }
    

Now the UIMenuItem works as expected:

But honestly, this really feels like a hack, and I would love Apple to fix this issue :-/

Thanks for Stephan Heilner for his answer: https://stackoverflow.com/a/42985441/4670400



来源:https://stackoverflow.com/questions/45538886/uimenuitem-selector-method-crash-in-wkwebview

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