Skip to content

Instantly share code, notes, and snippets.

@Revolucent
Created October 5, 2018 02:53
Show Gist options
  • Save Revolucent/416fb22b9c39e29ec35001378fc9752f to your computer and use it in GitHub Desktop.
Save Revolucent/416fb22b9c39e29ec35001378fc9752f to your computer and use it in GitHub Desktop.
isFirstResponder observable with RxSwift
import RxCocoa
import RxSwift
import UIKit
extension Reactive where Base: UIView {
var isFirstResponder: Observable<Bool> {
return Observable
.merge(
methodInvoked(#selector(UIView.becomeFirstResponder)),
methodInvoked(#selector(UIView.resignFirstResponder))
)
.map{ [weak view = self.base] _ in
view?.isFirstResponder ?? false
}
.startWith(base.isFirstResponder)
.distinctUntilChanged()
.share(replay: 1)
}
}
@graboosky
Copy link

It doesn't work.

@Revolucent
Copy link
Author

I haven't used this in quite a while. It worked at the time. What does not work?

@markst
Copy link

markst commented Jan 29, 2020

Seems to work for me...

@piechart
Copy link

piechart commented Dec 31, 2020

Works fine for me, thanks!

@nalexn
Copy link

nalexn commented Jun 26, 2024

This has stopped working in iOS 18, causing a stack overflow inside -[UITextInputUIResponderAccessibility becomeFirstResponder]

I wish isFirstResponder was backed by KVO, we'd simply used this:

extension Reactive where Base: UIResponder {
    var isFirstResponder: Observable<Bool> {
        return observe(\.isFirstResponder)
            .distinctUntilChanged()
    }
}

However, UIKit's views do not properly support KVO for isFirstResponder, so I had to re-enable it by overriding becomeFirstResponder and resignFirstResponder in every subclass that needs to be observed via rx.isFirstResponder:

override func becomeFirstResponder() -> Bool {
    willChangeValue(for: \.isFirstResponder)
    let result = super.becomeFirstResponder()
    didChangeValue(for: \.isFirstResponder)
    return result
}

override func resignFirstResponder() -> Bool {
    willChangeValue(for: \.isFirstResponder)
    let result = super.resignFirstResponder()
    didChangeValue(for: \.isFirstResponder)
    return result
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment