I have the following setup, where I want to load a GitHub user from the GitHub API based on the username that can be typed into a text field.
class SearchUserViewController: UIViewController {
@IBOutlet weak var nameTextField: UITextField!
@IBOutlet weak var activityIndicator: UIActivityIndicatorView!
@IBOutlet weak var repositoriesButton: UIButton!
let httpClient = HTTPClient()
let disposeBag = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
repositoriesButton.isEnabled = false
activityIndicator.hidesWhenStopped = true
setupUserObservable()
}
func setupUserObservable() {
let maybeUserObservable: Observable<User?>= nameTextField.rx.text
.throttle(0.5, scheduler: MainScheduler.instance)
.flatMapLatest { query in
self.fetchUser(username: query!)
.observeOn(MainScheduler.instance)
.catchErrorJustReturn(nil)
}
// bind button enabled property
maybeUserObservable
.map { return $0 != nil }
.bindTo(repositoriesButton.rx.isEnabled)
.addDisposableTo(disposeBag)
}
func fetchUser(username: String) -> Observable<User?> {
let url = httpClient.searchUserURL(for: username)!
let jsonObservable = URLSession.shared.rx.json(url: url)
let userObservable: Observable<User?> = jsonObservable.map { (json: Any) -> [String: Any]? in
guard let userInfo = json as? [String: Any] else {
return nil
}
return userInfo
}.map { (maybeUserInfo: [String: Any]?) -> User? in
guard let userInfo = maybeUserInfo else {
return nil
}
return self.httpClient.jsonToOptionalUser(userInfo: userInfo)
}
return userObservable
}
}
So, the setup is pretty standard I believe. It all works well so far, the repositoriesButton
's isEnabled
-property is only set to true
if a User
was found for the provided username.
However, I also would like to animate the activityIndicator
when a network request is going on. Ideally, I would also like to bind it's isAnimating
property using bindTo
. However, that doesn't work because the only info I get that I cam use for bindings based on the maybeUserObservable
is whether a User
was returned or not. So, this is not the same as saying whether a network request is ongoing or not.
So, how can I make sure that activityIndicator.isAnimating
is set to true
whenever a network request is started and to false
as soon as it returns - no matter whether a User
was actually returned or not?