Swifterswift: Recursive version of UIView.firstResponder property

Created on 4 Mar 2018  路  8Comments  路  Source: SwifterSwift/SwifterSwift

SwifterSwift has a property that finds a subview that is firstResponder from a view.
screen shot 2018-03-04 at 17 53 08

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
    }
discussion enhancement feature request

Most helpful comment

@LucianoPAlmeida For what reason do you want to find the first responder?

All 8 comments

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

  1. It is better to do another version that is recursive or update the firstResponder existing to handle this edge case.
  2. If the answer to the first one is updating the existing extension( which I prefer), I think it should become a method instead of a property.

@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.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

bjimenezned picture bjimenezned  路  3Comments

pawurb picture pawurb  路  3Comments

g001613001 picture g001613001  路  5Comments

fanglinwei picture fanglinwei  路  3Comments

omaralbeik picture omaralbeik  路  3Comments