问题
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:
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() }
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