Programmatically focus on a form in a webview (WKWebView)

前端 未结 6 1350
说谎
说谎 2020-12-09 03:50

It\'s possible with UIWebView with following:

[webView setKeyboardDisplayRequiresUserAction:NO]
Call some JS function

How can you do the sa

6条回答
  •  渐次进展
    2020-12-09 04:29

    I had to change @Mark's answer from an extension to a subclass as Swift 4.2 gave me an "All paths through this function will call itself" warning on the keyboardDisplayRequiresUserAction getter.

    import Foundation
    import WebKit
    
    typealias OldClosureType = @convention(c) (Any, Selector, UnsafeRawPointer, Bool, Bool, Any?) -> Void
    typealias NewClosureType = @convention(c) (Any, Selector, UnsafeRawPointer, Bool, Bool, Bool, Any?) -> Void
    
    class WebView: WKWebView {
    
        private var _keyboardDisplayRequiresUseraction = true
    
        var keyboardDisplayRequiresUserAction: Bool? {
            get {
                return _keyboardDisplayRequiresUseraction
            }
            set {
                _keyboardDisplayRequiresUseraction = newValue ?? true
                setKeyboardRequiresUserInteraction(_keyboardDisplayRequiresUseraction)
            }
        }
    
        private func setKeyboardRequiresUserInteraciton(_ value: Bool) {
            guard let WKContentViewClass: AnyClass = NSClassFromString("WKContentView") else {
                return print("Cannot find WKContentView class")
            }
    
            let oldSelector: Selector = sel_getUid("_startAssistingNode:userIsInteracting:blurPreviousNode:userObject:")
            let newSelector: Selector = sel_getUid("_startAssistingNode:userIsInteracting:blurPreviousNode:changingActivityState:userObject:")
    
            if let method = class_getInstanceMethod(WKContentViewClass, oldSelector) {
                let originalImp: IMP = method_getImplementation(method)
                let original: OldClosureType = unsafeBitCast(originalImp, to: OldClosureType.self)
                let block: @convention(block) (Any, UnsafeRawPointer, Bool, Bool, Any?) -> Void = { (me, arg0, arg1, arg2, arg3) in
                    original(me, oldSelector, arg0, !value, arg2, arg3)
                }
                let imp: IMP = imp_implementationWithBlock(block)
                method_setImplementation(method, imp)
            }
            if let method = class_getInstanceMethod(WKContentViewClass, newSelector) {
                let originalImp: IMP = method_getImplementation(method)
                let original: NewClosureType = unsafeBitCast(originalImp, to: NewClosureType.self)
                let block: @convention(block) (Any, UnsafeRawPointer, Bool, Bool, Bool, Any?) -> Void = { (me, arg0, arg1, arg2, arg3, arg4) in
                    original(me, newSelector, arg0, !value, arg2, arg3, arg4)
                }
                let imp: IMP = imp_implementationWithBlock(block)
                method_setImplementation(method, imp)
            }
        }
    }
    

    Tested on iOS 11.2 and 12.0

提交回复
热议问题