Skip to content

Commit 4ab7be0

Browse files
authored
fix: crash when unrecognized selector sent (#1153)
## 📜 Description Fixed a crash like `[react_native_keyboard_controller.KCTextInputCompositeDelegate scrollViewDidScroll:]: unrecognized selector sent to instance 0x110bbf400`. ## 💡 Motivation and Context My gut feeling is that during `responds` we have a delegate and we recognize the event. But when it comes to actual forwarding our delegate is unset, so we can't forward it to delegate, but we have to forward it to somehwere, so we send it to our `KCTextInputCompositeDelegate` delegate, our delegate can't handle it and we get a crash 🤯 As written in original implementation the issue seems to happen after navigation. And it actually makes sense - during navigation you may unmount a component, and unset delegate (or component may go into re-cycling pool and unset delegate). Anyway, we don't have a reproduction example and it's only my guess what can go wrong based on stacktrace and additional information provided. If my assumption is correct, then the best thing we can do is to ignore that crash (ideally we shouldn't be able to say that our delegate can handle a particular request, but it looks like it's impossible to implement, because it's timing issue). So in this PR I simply added a method for handling the exception and added a logger (based on logger information we can debug the issue further). Closes #1119 ## 📢 Changelog <!-- High level overview of important changes --> <!-- For example: fixed status bar manipulation; added new types declarations; --> <!-- If your changes don't affect one of platform/language below - then remove this platform/language --> ### iOS - added error handler via overriding `doesNotRecognizeSelector` with proper logging; ## 🤔 How Has This Been Tested? Since there is no way to test it in example app I re-worked code so that `forwardingTarget` always throws an exception: ```swift override func forwardingTarget(for aSelector: Selector!) -> Any? { return super.forwardingTarget(for: aSelector) } ``` My delegate doesn't implement many methods, so if you start to type in multiline input you'll get a crash almost instantly with the same stacktrace (that it happened in `forwardingTarget`). With this PR changes you'll not get a crash. ## 📸 Screenshots (if appropriate): |Before|After| |-------|-----| |<video src="https://github.com/user-attachments/assets/2eb810bb-3487-4fac-9664-d5420daa6044">|<video src="https://github.com/user-attachments/assets/1e150e8f-0220-4505-8ef9-0234425c6b5a">| ## 📝 Checklist - [x] CI successfully passed - [x] I added new mocks and corresponding unit-tests if library API was changed
1 parent 89fa05d commit 4ab7be0

File tree

1 file changed

+13
-0
lines changed

1 file changed

+13
-0
lines changed

ios/delegates/KCTextInputCompositeDelegate.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,4 +221,17 @@ class KCTextInputCompositeDelegate: NSObject, UITextViewDelegate, UITextFieldDel
221221
}
222222
return super.forwardingTarget(for: aSelector)
223223
}
224+
225+
override func doesNotRecognizeSelector(_ aSelector: Selector!) {
226+
let className = NSStringFromClass(type(of: self))
227+
let selectorName = NSStringFromSelector(aSelector)
228+
229+
print("⚠️ [\(className)] does not recognize selector: \(selectorName)")
230+
231+
if let delegate = activeDelegate {
232+
print("ℹ️ activeDelegate: \(type(of: delegate)) (responds: \(delegate.responds(to: aSelector)))")
233+
} else {
234+
print("ℹ️ activeDelegate is nil")
235+
}
236+
}
224237
}

0 commit comments

Comments
 (0)