iOS 解决方案

iOS-Native端禁用WebView上的menu item

2018-11-13  本文已影响0人  转岗做JAVA

举个例子

项目中的webView页面有可能需要禁用全选功能,可以在h5端实现,也可以通过native实现。native端的思路是先找到实现了selectAll(_:)方法的View,然后通过method swizzling修改View实现的canPerformAction(_:withSender:)方法,使其不响应selectAll(_:)方法。下面的代码展示如何通过native端禁用全选功能:

    //使用BFS算法查找实现了selectAll方法的视图。对结果进行测试后得出:
    //1.UIWebView中是由UIWebBrowserView控制
    //2.WKWebView中是由WKContentView控制
    func findSelectAllActionViews() -> [UIView] {
        var queue = [UIView]()
        queue.append(wkWebView)
        var views = [UIView]()
        while queue.count > 0 {
            let subView = queue.removeFirst()
            if subView.responds(to: #selector(selectAll(_:))) {
                views.append(subView)
            }
            queue.append(contentsOf: subView.subviews)
        }
        return views
    }

    // 线上使用时直接对UIWebBrowserView或WKContentView进行替换。
    func disableViewSelectAllAction() {
        let className1: AnyClass = NSClassFromString("UIWebBrowserView")!
        let className2: AnyClass = NSClassFromString("WKContentView")!
        self.findSelectAllActionViews().forEach { actionView in
            if actionView.isKind(of: className1) || actionView.isKind(of: className2)  {
                let customSelector = #selector(ct_canPerformAction(_:withSender:))
                if let m1 = class_getInstanceMethod(actionView.classForCoder, #selector(canPerformAction(_:withSender:))) ,
                    let imp = class_getMethodImplementation(self.classForCoder, customSelector),
                    class_addMethod(actionView.classForCoder, customSelector, imp, method_getTypeEncoding(m1)) {
                    let m2 = class_getInstanceMethod(actionView.classForCoder, customSelector)!
                    method_exchangeImplementations(m1, m2)
                }
            }
        }
    }

    //禁用掉selectAll:方法,其他不禁用。
    //效果就是全选不能用,其他的menu item跟以前的逻辑一样
    @objc dynamic func ct_canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
        return action.description != "selectAll:" && ct_canPerformAction(action, withSender: sender)
    }

如果要禁用其他的menu item,也可用同样的方式;禁用所有的menu item的话,直接return false就可以了。

参考文章

https://www.jianshu.com/p/dd7452d3d123

上一篇下一篇

猜你喜欢

热点阅读