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)的第四个参数,但是不起做用