Open devgeektech opened 4 years ago
i have the same bug in ios 13 , and ifix it like this
RichEditorDelegate
func richEditorTookFocus(_ editor: RichEditorView) { DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.5){ editor.focus() } }
That solution refocuses the editor but ignores where the user tapped and always puts the cursor at the end. Is there a way to get it to refocus on the right position?
I think I found a better solution. Create a subclass of RichEditorView and add another target to the gesture recognizer. Save the point when it gets a tap and use that when the delegate refocuses the editor
subclass:
import UIKit
import RichEditorView
class FBRichEditor: RichEditorView {
public var lastFocus: CGPoint?
public var tap: UITapGestureRecognizer!
public override init(frame: CGRect) {
super.init(frame: frame)
configure()
}
required public init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
configure()
}
public func configure() {
tap = super.gestureRecognizers![0] as? UITapGestureRecognizer
tap.addTarget(self, action: #selector(wasTapped))
tap.delegate = self
addGestureRecognizer(tap)
}
@objc private func wasTapped() {
lastFocus = tap.location(in: super.webView)
}
}
change richEditorTookFocus function to this:
func richEditorTookFocus(_ editor: RichEditorView) {
DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.5) {
if self.richTextEditor.lastFocus != nil {
editor.focus(at: self.richTextEditor.lastFocus!)
} else {
editor.focus()
}
}
}
For my work this: @objc private func viewWasTapped() { let point = tapRecognizer.location(in: webView) DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.5){ self.focus(at: point) }
}
i have the same bug in ios 13 , and ifix it like this
RichEditorDelegate
func richEditorTookFocus(_ editor: RichEditorView) { DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.5){ editor.focus() } }
Thanks this works for me.
I think I found a better solution. Create a subclass of RichEditorView and add another target to the gesture recognizer. Save the point when it gets a tap and use that when the delegate refocuses the editor
subclass:
import UIKit import RichEditorView class FBRichEditor: RichEditorView { public var lastFocus: CGPoint? public var tap: UITapGestureRecognizer! public override init(frame: CGRect) { super.init(frame: frame) configure() } required public init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) configure() } public func configure() { tap = super.gestureRecognizers![0] as? UITapGestureRecognizer tap.addTarget(self, action: #selector(wasTapped)) tap.delegate = self addGestureRecognizer(tap) } @objc private func wasTapped() { lastFocus = tap.location(in: super.webView) } }
change richEditorTookFocus function to this:
func richEditorTookFocus(_ editor: RichEditorView) { DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + 0.5) { if self.richTextEditor.lastFocus != nil { editor.focus(at: self.richTextEditor.lastFocus!) } else { editor.focus() } } }
This seems like a good workaround! I ended up adding
func richEditorLostFocus(_ editor: RichEditorView) {
self.richTextEditor.lastFocus = nil
}
so if you lose focus and then you programmatically need to give it focus again without a touch, the cursor appears at the end of the line as it should be
Still there has to be a reason why this is happening
I tried the referenced answer
additionalSafeAreaInsets.left = 12.0
additionalSafeAreaInsets.right = 12.0
but that did nothing
Step 1 : Add focus
self.editorView.focus(at: .zero)
Step 2 : Add extension in RichEditorView typealias OldClosureType = @convention(c) (Any, Selector, UnsafeRawPointer, Bool, Bool, Any?) -> Void typealias NewClosureType = @convention(c) (Any, Selector, UnsafeRawPointer, Bool, Bool, Bool, Any?) -> Void
extension WKWebView{ 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)
}
}
}
Finally set keyboardDisplayRequiresUserAction in private func setup()
webView.keyboardDisplayRequiresUserAction = false
Hello @cjwirth
Keyboard cursor appears only one time and suddenly disappear when I first tap on editor . But when I tap second time again on editor, cursor is showing. For the first time cursor disappear but keyboard exist. And User cannot type as cursor in not there.