RichEditorView
RichEditorView copied to clipboard
becomeFirstResponder or focus not working
Hi :) On simulator here on 14.5, i can't get working becomeFirstResponder or focus method. It's working fine with finger tap, showing the keyboard, but programmatically never.
I'm using it inside tableview cell, and try to add a new cell, then show the focus directly, and it's never fired. Look like the method in js is called (with breakpoints) but never get the focus in the simulator.
Any idea or same reaction ? thx !
When you do becomeFirstResponder
, have you tried just typing on your keyboard? Does the toolbar appear? Additionally, if you have an iPhone do you mind trying it out on there programmatically and seeing if the keyboard appears? There is also a method called focus
. Do you mind trying that out as well?
Please let me know what happens for each of those requests; really helps me debug :) Cheers!
No keyboard appeared, i'm on iPad devices, the editor view with the decoded html appeard well, but no focus and so no keyboard. I'm using this object only on iPad. I've tried becomeFirstResponder and focus, even focusAt, nohting but the callback richEditorTookFocus is called everytime, so maybe something related to the web part.
Could a css could prevent the focus programmatically ? Because it works well when i tap. I don't think there is a way to simulate a tap without UItouch event.
Or, which could be a bad news, could be related to that : the removal of keyboardDisplayRequiresUserAction not available in WKWebView compare to UIWebView ?
https://developer.apple.com/documentation/uikit/uiwebview/1617967-keyboarddisplayrequiresuseractio#discussion
Could be a solution ? https://stackoverflow.com/questions/32449870/programmatically-focus-on-a-form-in-a-webview-wkwebview
Because i've event put a RE.focus() at the end of document ready on rich_editor.js and it's called after (breakpoint and js debug fired) but no focus or keyboard shown :(
ok, it was that ... thx Apple for always breaking everything ;) anyway here some code i've used
import WebKit
import Foundation
typealias OldClosureType = @convention(c) (Any, Selector, UnsafeRawPointer, Bool, Bool, Any?) -> Void
typealias NewClosureType = @convention(c) (Any, Selector, UnsafeRawPointer, Bool, Bool, Bool, Any?) -> Void
public class RichEditorWebView: WKWebView {
public var accessoryView: UIView?
public override var inputAccessoryView: UIView? {
return accessoryView
}
private var _keyboardDisplayRequiresUseraction = true
public var keyboardDisplayRequiresUserAction: Bool? {
get {
return self.keyboardDisplayRequiresUserAction
}
set {
self.setKeyboardRequiresUserInteraction(newValue ?? true)
}
}
func setKeyboardRequiresUserInteraction( _ value: Bool) {
guard let WKContentView: AnyClass = NSClassFromString("WKContentView") else {
print("keyboardDisplayRequiresUserAction extension: Cannot find the WKContentView class")
return
}
// For iOS 10, *
let sel_10: Selector = sel_getUid("_startAssistingNode:userIsInteracting:blurPreviousNode:userObject:")
// For iOS 11.3, *
let sel_11_3: Selector = sel_getUid("_startAssistingNode:userIsInteracting:blurPreviousNode:changingActivityState:userObject:")
// For iOS 12.2, *
let sel_12_2: Selector = sel_getUid("_elementDidFocus:userIsInteracting:blurPreviousNode:changingActivityState:userObject:")
// For iOS 13.0, *
let sel_13_0: Selector = sel_getUid("_elementDidFocus:userIsInteracting:blurPreviousNode:activityStateChanges:userObject:")
if let method = class_getInstanceMethod(WKContentView, sel_10) {
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, sel_10, arg0, !value, arg2, arg3)
}
let imp: IMP = imp_implementationWithBlock(block)
method_setImplementation(method, imp)
}
if let method = class_getInstanceMethod(WKContentView, sel_11_3) {
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, sel_11_3, arg0, !value, arg2, arg3, arg4)
}
let imp: IMP = imp_implementationWithBlock(block)
method_setImplementation(method, imp)
}
if let method = class_getInstanceMethod(WKContentView, sel_12_2) {
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, sel_12_2, arg0, !value, arg2, arg3, arg4)
}
let imp: IMP = imp_implementationWithBlock(block)
method_setImplementation(method, imp)
}
if let method = class_getInstanceMethod(WKContentView, sel_13_0) {
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, sel_13_0, arg0, !value, arg2, arg3, arg4)
}
let imp: IMP = imp_implementationWithBlock(block)
method_setImplementation(method, imp)
}
}
}
and then in setup part
webView.keyboardDisplayRequiresUserAction = false
look like it's working here on iPad ios 14.5 :) i don't like private method, but look like there is no other options here, or i didn't look enough on WKWebView docs.
Thanks for this investigation @Jcragons ! ~~Did you have this issue on previous iPadOS or iOS versions?~~ And if you'd like, a PR is also appreciated :)
Scratch that: I see:
// For iOS 10, *
let sel_10: Selector = sel_getUid("_startAssistingNode:userIsInteracting:blurPreviousNode:userObject:")
// For iOS 11.3, *
let sel_11_3: Selector = sel_getUid("_startAssistingNode:userIsInteracting:blurPreviousNode:changingActivityState:userObject:")
// For iOS 12.2, *
let sel_12_2: Selector = sel_getUid("_elementDidFocus:userIsInteracting:blurPreviousNode:changingActivityState:userObject:")
// For iOS 13.0, *
let sel_13_0: Selector = sel_getUid("_elementDidFocus:userIsInteracting:blurPreviousNode:activityStateChanges:userObject:")
which is... interesting to say the least.
Yeah i assume this removal from apple render people crazy since everyone need to move from UIWebView to WKWebView. Didn't try under < ios12 or right now anything else than ipadOs, but i assume it's global. I hope the private method hack will last, look like on ios14 they didn't change method signature, but i'll cross finder at every release ;)
I'm not directly using the files from github, but i can check for a PR as soon as i finish my inegration :)