iOS WKWebView控制自动弹起键盘

iOS在UIWebView时代,系统提供了keyboardRequiresUserInteraction属性,用于处理webView自动弹起键盘,但是在WKWebView,该方法被废弃,需要自己手动实现,代码如下

var oldImp: Any?

extension WKWebView {
    
    /// 这个属性UIWebview有,WKWebView要自己实现
    func setKeyboardRequiresUserInteraction( _ value: Bool) {
        
        guard
            let WKContentViewClass: AnyClass = NSClassFromString("WKContentView") else {
                print("Cannot find the WKContentView class")
                return
        }
        
        let olderSelector: Selector = sel_getUid("_startAssistingNode:userIsInteracting:blurPreviousNode:userObject:")
        let newSelector: Selector = sel_getUid("_startAssistingNode:userIsInteracting:blurPreviousNode:changingActivityState:userObject:")
        let newerSelector: Selector = sel_getUid("_elementDidFocus:userIsInteracting:blurPreviousNode:changingActivityState:userObject:")
        let ios13Selector: Selector = sel_getUid("_elementDidFocus:userIsInteracting:blurPreviousNode:activityStateChanges:userObject:")
        
        if let method = class_getInstanceMethod(WKContentViewClass, olderSelector) {
            let originalImp: IMP = method_getImplementation(method)
            let original: OlderClosureType = unsafeBitCast(originalImp, to: OlderClosureType.self)
            let block : @convention(block) (Any, UnsafeRawPointer, Bool, Bool, Any?) -> Void = { (me, arg0, arg1, arg2, arg3) in
                original(me, olderSelector, arg0, true, arg2, arg3)
            }
            let imp: IMP = imp_implementationWithBlock(block)
            method_setImplementation(method, imp)
        }
        
        if let method = class_getInstanceMethod(WKContentViewClass, newSelector) {
            swizzleAutofocusMethod(className: WKContentViewClass, method: method, selector: newSelector, value: value)
        }
        
        if let method = class_getInstanceMethod(WKContentViewClass, newerSelector) {
            swizzleAutofocusMethod(className: WKContentViewClass, method: method, selector: newerSelector, value: value)
        }
        
        if let method = class_getInstanceMethod(WKContentViewClass, ios13Selector) {
            swizzleAutofocusMethod(className: WKContentViewClass, method: method, selector: ios13Selector, value: value)
        }
    }
    
    func swizzleAutofocusMethod(className: AnyClass, method: Method, selector: Selector, value: Bool) {

        if oldImp == nil {
            if !value {
                let originalImp: IMP = method_getImplementation(method)
                oldImp = originalImp
                
                let original: NewerClosureType = unsafeBitCast(originalImp, to: NewerClosureType.self)
                let block : @convention(block) (Any, UnsafeRawPointer, Bool, Bool, Bool, Any?) -> Void = { (me, arg0, arg1, arg2, arg3, arg4) in
                    original(me, selector, arg0, !value, arg2, arg3, arg4)
                }
                let imp: IMP = imp_implementationWithBlock(block)
                method_setImplementation(method, imp)
            }
            
        } else {
            if value {
                if let old = oldImp as? IMP {
                    method_setImplementation(method, old)
                    oldImp = nil
                }
            }
        }
    }
}

说明:为了实现,部分页面允许自动弹起键盘,部分页面禁止的需求,需要手动保存一下我们替换之前的IMP,在不需要替换键盘的时候,把老的给重新添加上

需要注意的是,webKit的签名源码会随着系统变动,所以在最新系统,可能会出现bug,需要及时对比官网添加

备注:曾尝试替换original(me, selector, arg0, true, arg2, arg3, arg4)的第四个参数,但是不起做用

你可能感兴趣的:(iOS WKWebView控制自动弹起键盘)