ios - delayed reaction to NSURLSession response -
i'm having odd problem swift application seemingly sequential sequence of events resulting in unsequential output. have button click operation looks following (where self.indicator uiactivityindicatorview , self.errorbox uilabel):
func onsigninclick(sender: uibutton!) { let url = nsurl_removed_from_example var request = nsmutableurlrequest(url: url!) request.httpmethod = "post" request.addvalue("application/json", forhttpheaderfield: "content-type") request.addvalue("application/json", forhttpheaderfield: "accept") var data = [ "u": self.usernamebox.text, "p": self.passwordbox.text ] var err: nserror? request.httpbody = nsjsonserialization.datawithjsonobject(data, options: nil, error: &err) let config = nsurlsessionconfiguration.defaultsessionconfiguration() let session = nsurlsession(configuration: config) uiapplication.sharedapplication().networkactivityindicatorvisible = true self.indicator.startanimating() self.errorbox.text = "" session.datataskwithrequest(request, completionhandler: { (data, response, error) in self.indicator.stopanimating() uiapplication.sharedapplication().networkactivityindicatorvisible = false if error != nil { logger.warn("sign in error: \(error.localizeddescription)") } else { let json = parser.parsejson(data) // returns swiftyjson object logger.info("received response: \(json.stringvalue)") if json["result"].boolvalue { // success self.dismissviewcontrolleranimated(true, completion: nil) nsnotificationcenter.defaultcenter().postnotificationname(account.loginnotification, object: self) } else { // additional errors within message error in json["errors"]["details"].arrayvalue { let code = error["code"].intvalue let message = error["message"].stringvalue logger.error("internal error \(code): \(message)") if code == 1001 { self.errorbox.text = "you must specify username , password" } else if code == 1002 { self.errorbox.text = "incorrect username or password" } else { self.errorbox.text = "unknown error, error code: \(code)" } } } } }).resume() } i send request , receive response. when request sent spinning indicator appears , intent disappear message received.
the problem request makes way before ui "reacts" it. in logic above can see log messages. see uiapplication.sharedapplication().networkactivityindicatorvisible icon disappear message appears in logs. yet indicator (which told stop animating right before) continues spin 5 seconds or so. same applies error message, appears 5 seconds later. have self.indicator.hideswhenstopped = true defined in loadview.
i can't figure out what's happening. why neither indicator nor error box update until later on? if redraw asynchronous, shouldn't take 5 seconds occur.
also, tried timing it, delay seems vary well. 5 seconds, long 30.
the completion handler provided datawithrequest:completionhandler: method called on delegatequeue of nsurlsession. default queue serial nsoperationqueue created nsurlsession, i.e. not main thread. then, i'm not sure ios provides behaviour guarantees ui updates ever occurring if initiated outside main thread.
in ios, ui operations must happen on main thread. when tell activity indicator cease animating nothing happen until main thread notices update.
try setting delegatequeue of nsurlsession main queue, or alternatively can try using dispatch_async main thread ui updates:
self.indicator.stopanimating() uiapplication.sharedapplication().networkactivityindicatorvisible = false edit showing delegatequeue approach:
while delegatequeue property read-only, can set when creating nsurlsession specialized init method:
init(configuration configuration: nsurlsessionconfiguration, delegate delegate: nsurlsessiondelegate?, delegatequeue queue: nsoperationqueue?)
Comments
Post a Comment