SwifterSwift has a property that finds a subview that is firstResponder from a view.

But this extension just searches in the subviews, and not recursive in the subviews of subviews of the subviews and so on...
The proposal implements a recursive version that searches recursively in the view hierarchy
I implemented a version, that could be a start for who takes this
func recursiveFirstResponder() -> UIResponder? {
guard !subviews.isEmpty else { return nil }
for subview in subviews {
if subview.isFirstResponder {
return subview
} else {
if let responder = subview.recursiveFirstResponder() {
return responder
}
}
}
return nil
}
How much of a concern is the performance of this method? It seems to me that the preposed implementation would be pretty slow.
Hey @calebkleveter the more performant the best :)
Indeed this is not the most performant implementation, but actually is very simple to improve :))
I've implemented a better version
func firstResponder() -> UIView? {
guard
!isFirstResponder else { return self }
guard
!subviews.isEmpty else { return nil }
if let responder = subviews.first(where: { $0.isFirstResponder }) {
return responder
}
for subview in subviews {
if let responder = subview.firstResponder() {
return responder
}
}
return nil
}
Didn't send a PR because I think there are some points need to discuss
@omaralbeik, @SD10 what do you guys think?
@LucianoPAlmeida For what reason do you want to find the first responder?
@SD10 It's very rare, but sometimes I have to access a text field inside an keyboard event handler for example, in a generic way, like a BaseViewController. But, the use case where I tried to use the UIView.firstResponder extension and notice that it was not recursive, was to find a textField that was inside a cell, on a tableView.
@LucianoPAlmeida I think the best way would be to tell UIApplication to resign the first responder. Events bubble up through theUIResponder chain to UIApplication before exiting.
UIApplication.shared.sendAction(#selector(resignFirstResponder), to: nil, for: nil, from: nil)
@SD10 this works only if I wanted just resign. But there's cases where I actually needs the instance of the text field to perform some operations on it :)
Sent with GitHawk
If a iterative solution is not slower then a recursive solution like in sort algorithms i would pick the iterative solution. Lower complexity and smaller memory food print.
@SD10 that's an extension we should have to simple resign first responder without knowing the first responder explicitly.
Most helpful comment
@LucianoPAlmeida For what reason do you want to find the first responder?