I'm trying to figure out if network requests handling can be implemented suitable to my needs using ReactiveSwift and RAC5.
Under topic Migrate from RACSignal to ReactiveSwift or RAC5 I was told it can be done with SignalProducer, but digging deeper into it didn't give me expected results
So, I would want to have:
1. Each time text changes in textField send request (search by keyword).
2. Once user closes current ViewController, the current request should be cancelled automatically
3. Have an ability to cancel request once keyword is changed
Here is what I have
self.textField.reactive.continuousTextValues.skipNil().filter({ (value) -> Bool in
return value.characters.count > 0
}).observeValues { [unowned self] (value) in
self.fetchSignalDisposable?.dispose()
self.fetchSignal = self.producerFor(keyword: value).on(started: {
print("started")
}, failed: { (error) in
print("error")
}, completed: {
print("completed")
}, value: { [unowned self] (items) in
print("value")
self.items.append(contentsOf: items)
self.tableView.reloadData()
})
self.fetchSignalDisposable = self.fetchSignal!.start()
}
And here is producer initializer
return SignalProducer<Any, NSError> { (observer, disposable) in
let task: URLSessionDataTask? = NetworkClient.fetchRequestWith(uri: "test", parameters: ["keyword" : keyword], success: { response in
observer.send(value: response)
observer.sendCompleted()
}, failure: { error in
observer.send(error: error)
observer.sendCompleted()
})
disposable += {
task?.cancel()
}
}
Notes:
1. Sometimes I want to have kinda "both handler block" that would be called on both success and errors, so stuff like hiding loading indicators can be done under that block.
Few problems/questions here:
1. Once I close VC (dismiss action) observeValue handler is called one more time. It can be fixed by adding .skipRepeats()
, but I guess it is just a workaround and not an exact solution. I would want to not have this observer active anymore, if I close VC
2. completed
block not called in case of error, even if I call it manually right after calling send(error: error)
3. If request is still loading and I close VC, it is not getting disposed automatically, which looks strange to me. I thought dispose block will be called automatically once viewController lose reference to signalProducer. Even calling self.fetchSignalDisposable?.dispose()
in deinit
method of VC doesn't cancel request. It still finishes request and calls value
handler which leads to crash with Bad Access error
My personal needs are:
1. Have some kind of "both" block that will be called after both success and failed cases of request
2. All observers for textFields' text values must be removed and not be active anymore once I close VC
3. Network request must be cancelled right when I close VC
P.S.: Of course, thanks to everyone who read this huge post and spent time helping me!