diff --git a/ios/extensions/Notification.swift b/ios/extensions/Notification.swift index 9874fd229..cf5634673 100644 --- a/ios/extensions/Notification.swift +++ b/ios/extensions/Notification.swift @@ -18,4 +18,6 @@ extension Notification { extension Notification.Name { static let shouldIgnoreKeyboardEvents = Notification.Name("shouldIgnoreKeyboardEvents") + static let didBecomeFirstResponder = Notification.Name("didBecomeFirstResponder") + static let didResignFirstResponder = Notification.Name("didResignFirstResponder") } diff --git a/ios/observers/FocusedInputObserver.swift b/ios/observers/FocusedInputObserver.swift index 3004dd39a..3e63e1701 100644 --- a/ios/observers/FocusedInputObserver.swift +++ b/ios/observers/FocusedInputObserver.swift @@ -77,13 +77,13 @@ public class FocusedInputObserver: NSObject { NotificationCenter.default.addObserver( self, selector: #selector(keyboardWillShow), - name: UIResponder.keyboardWillShowNotification, + name: .didBecomeFirstResponder, object: nil ) NotificationCenter.default.addObserver( self, selector: #selector(keyboardWillHide), - name: UIResponder.keyboardWillHideNotification, + name: .didResignFirstResponder, object: nil ) } diff --git a/ios/swizzling/UIResponderSwizzle.swift b/ios/swizzling/UIResponderSwizzle.swift index b0484910d..a18d0f912 100644 --- a/ios/swizzling/UIResponderSwizzle.swift +++ b/ios/swizzling/UIResponderSwizzle.swift @@ -9,6 +9,7 @@ import Foundation import UIKit private var originalResignFirstResponder: IMP? +private var originalBecomeFirstResponder: IMP? @objc extension UIResponder { @@ -55,6 +56,44 @@ extension UIResponder { typealias Function = @convention(c) (AnyObject, Selector) -> Bool let castOriginalResignFirstResponder = unsafeBitCast(originalResignFirstResponder, to: Function.self) let result = castOriginalResignFirstResponder(self, selector) + + if result { + NotificationCenter.default.post(name: .didResignFirstResponder, object: self) + } + return result } + + public static func swizzleBecomeFirstResponder() { + let originalSelector = #selector(becomeFirstResponder) + + guard let originalMethod = class_getInstanceMethod(UIResponder.self, originalSelector) else { + return + } + + originalBecomeFirstResponder = method_getImplementation(originalMethod) + + let swizzledImplementation: @convention(block) (UIResponder) -> Bool = { (self) in + // Call the original implementation + let didBecomeFirstResponder = self.callOriginalBecomeFirstResponder(originalSelector) + + if didBecomeFirstResponder { + // Post a notification when the responder becomes first responder + NotificationCenter.default.post(name: .didBecomeFirstResponder, object: self) + } + + return didBecomeFirstResponder + } + + let implementation = imp_implementationWithBlock(swizzledImplementation) + method_setImplementation(originalMethod, implementation) + } + + private func callOriginalBecomeFirstResponder(_ selector: Selector) -> Bool { + guard let originalBecomeFirstResponder = originalBecomeFirstResponder else { return false } + typealias Function = @convention(c) (AnyObject, Selector) -> Bool + let castOriginalBecomeFirstResponder = unsafeBitCast(originalBecomeFirstResponder, to: Function.self) + let result = castOriginalBecomeFirstResponder(self, selector) + return result + } }