我的Swift应用程序出现了一个奇怪的问题,其中看似连续的事件序列导致无关紧要的输出。我有一个按钮单击操作,如下所示(其中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
for 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 and password"
} else if code == 1002 {
self.errorBox.text = "Incorrect username or password"
} else {
self.errorBox.text = "Unknown error, error code: \(code)"
}
}
}
}
}).resume()
}
我发送请求并收到回复。发送请求时,会出现旋转指示符,并且一旦收到消息,其意图就是消失。
问题在于,请求会在UI"做出反应之前使其恢复正常。它。在上面的逻辑中,您可以看到日志消息。消息一出现在日志中,我也会看到UIApplication.sharedApplication().networkActivityIndicatorVisible
图标消失。然而,指示器(被告知之前停止动画)继续旋转另外5秒左右。同样适用于错误消息,该消息仅在约5秒后出现。我在loadView中也定义了self.indicator.hidesWhenStopped = true
。
我无法弄清楚发生了什么。为什么指示器和错误框都不会更新到更晚?即使重绘是异步的,也不应该花5秒钟。
另外,我尝试计时,延迟似乎也有所不同。有时5秒,有时长达30秒。
答案 0 :(得分:2)
dataWithRequest:completionHandler:
方法提供的完成处理程序将在delegateQueue
的{{1}}上调用。默认情况下,此队列是为NSURLSession
创建的序列NSOperationQueue
,即不是主线程。即使这样,我也不确定iOS是否为在主线程之外启动的UI更新提供了任何行为保证。
在iOS中,UI操作必须在主线程上进行。当你告诉你的活动指示器停止动画时,在主线程注意到更新之前不会发生任何事情。
尝试将NSURLSession
的{{1}}设置为主要队列,或者您也可以尝试使用delegateQueue
到主线程以获取UI更新:
NSURLSession
修改显示dispatch_async
方法:
虽然self.indicator.stopAnimating()
UIApplication.sharedApplication().networkActivityIndicatorVisible = false
属性是只读的,但您可以在使用专门的init方法创建delegateQueue
时设置它:
delegateQueue