问题
I am using Siesta for REST calls and I am trying to create a simple ResourceObserver to display a SVProgressHUD.
open class SVProgressHUDResourceObserver: ResourceObserver {
static let sharedInstance = SVProgressHUDResourceObserver()
// Show/Hide SVProgressHUD
public func resourceRequestProgress(for resource: Resource, progress: Double) {
print("SVProgressHUDResourceObserver resourceRequestProgress - progress=\(progress)")
if progress == 1 {
print("SVProgressHUD.dismiss()")
SVProgressHUD.dismiss()
} else if !SVProgressHUD.isVisible() {
print("show()")
SVProgressHUD.show()
}
}
public func resourceChanged(_ resource: Resource, event: ResourceEvent) {
print("SVProgressHUDResourceObserver resourceChanged event=\(event)")
}
}
Since it's a singleton I add the observer using a weak reference:
@discardableResult func login(_ username: String, _ password: String,
onSuccess: @escaping (LoginResponse) -> Void,
onFailure: @escaping (Int?, String) -> Void) -> Request {
return service.resource("/app/v1/authentication/login")
.addObserver(SVProgressHUDResourceObserver.sharedInstance)
.request(.post, json: [
"username": username,
"password": password
])
.onSuccess { entity in
guard let loginResponse: LoginResponse = entity.typedContent() else {
onFailure(0, "JSON parsing error")
return
}
self.authToken = loginResponse.session.token
SessionManager.beginNewSession(loginResponse)
onSuccess(loginResponse)
}
.onFailure { (error) in
onFailure(error.httpStatusCode, error.userMessage)
}
}
I purposely added a 10 second delay to the login however the SVProgressHUD never displays, in-fact the resourceRequestProgress method is never called. The authentication process work great.
The log output is:
SVProgressHUDResourceObserver resourceChanged event=observerAdded
SVProgressHUDResourceObserver resourceChanged event=newData(wipe)
Any assistance on getting this to work would be greatly appreciated.
回答1:
There is a difference in Siesta between:
- the state of the whole resource itself, which Siesta caches and keeps around for anyone to observe, and
- the results of individual requests relating to the resource, which Siesta sends to request hooks but ultimately discards once the request is deallocated.
Note that with #1, observers keep getting notifications if anyone updates the state of the resource, whereas with #2 only the hook specifically registered for that request get notifications.
These two carry different kinds of information. #1 is for updates to the ongoing shared truth of the state of a resource (“the current user’s profile”) whereas #2 is for updates about the state of a specific action on the resource (“changing the user’s password”).
Take some time to digest “Request vs. Load” in the user guide. Then, once you’ve made sense of that, read on.
In this code, you are attaching SVProgressHUDResourceObserver.sharedInstance
as an observer of the resource itself:
return service.resource("/app/v1/authentication/login")
.addObserver(SVProgressHUDResourceObserver.sharedInstance)
…which means it will only get notifications of load()
requests. But you never load
it; you only request
it:
.request(.post, json: [
"username": username,
"password": password
])
…which means that only the request hooks (onSuccess
, onFailure
) that you attach to that specific request will be notified that it’s completed.
If you only need a progress bar, ditch ResourceObserver
and use the onProgress hook of the request instead.
(If you need to save the result of the login, then the user guide lays out how to update the resource’s state in response to a post request. However, it looks like you are already storing the auth credentials through other means, which is a typical and fine approach.)
来源:https://stackoverflow.com/questions/49620486/ios-swift-siesta-resourceobserver-resourcerequestprogress-never-called