何时使用主队列
When to use main queue
我知道 UI 的任何更新都应该在主队列中 运行 使用以下语法:
dispatch_async(dispatch_get_main_queue()) {
UI update code here
}
其他这些案例呢?
在我的 viewDidLoad() 中,我有代码来风格化导航栏和工具栏,如下所示:
let nav = self.navigationController?.navigationBar
nav?.barStyle = UIBarStyle.Default
nav?.tintColor = UIColor.blackColor()
nav?.barTintColor = UIColor(red:133.0/255, green:182.0/255, blue:189.0/255, alpha:1.0)
let toolBar = self.navigationController?.toolbar
toolBar?.barTintColor = UIColor(red:231/255, green:111/255, blue:19.0/255, alpha:1.0)
toolBar?.tintColor = UIColor.blackColor()
我是否也应该将此代码包装在主队列中?
在我的 tableView cellForRowAtIndexPath 函数中,我是否也应该包装所有设置主队列中每个 table 单元格的 UI 的代码?
当我呈现一个新的模态控制器(self.presentViewController(modalController,animated:true,completion:nil)时,我应该将它包装在主队列中吗?
你所有问题的答案是"no"
除非文档中指定,否则所有 UIKit 函数都将在主队列上调用。
通常,在调用异步函数后,您需要在主队列上专门 运行 完成处理程序 运行 在后台队列上。像……
// downloadImage is some func where the
// completion handler runs on a background queue
downloadImage(completion: { image in
DispatchQueue.main.async {
self.imageView.image = image
}
})
是的,只有在后台队列上已经异步执行某个函数时,您才应该调用主队列。而这往往不会自行发生。
正如 Ashley 所说,UIKit 方法会自动从主队列中调用——它们就是这样。那么按理说,有些框架有自动从后台队列调用的方法。
我知道 URLSession 的 dataTask 的 resume 函数会自动在后台队列上执行(这样应用程序就不会因网络连接而变慢),这意味着完成处理程序之后执行也适用于后台队列。这就是为什么在完成处理程序中发生的任何 UI 更新 当然需要 对主队列的调用。
let dataTask = URLSession.shared.dataTask(with: request) {
// begin completion handler
(data, response, error) in
guard error == nil else { print("error \(error.debugDescription)"); return }
guard let data = data else { print("no data"); return }
do {
if let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [[String: Any]] {
print("sending returned JSON to handler")
self.responseHandler.handleAPIResponse(jsonArray: json)
>>>> DispatchQueue.main.async { <<<<
self.tableView.reloadData()
}
}
} catch {
print("get tasks JSONSerialization error")
}
}
dataTask.resume()
我知道 UI 的任何更新都应该在主队列中 运行 使用以下语法:
dispatch_async(dispatch_get_main_queue()) {
UI update code here
}
其他这些案例呢?
在我的 viewDidLoad() 中,我有代码来风格化导航栏和工具栏,如下所示:
let nav = self.navigationController?.navigationBar
nav?.barStyle = UIBarStyle.Default
nav?.tintColor = UIColor.blackColor()
nav?.barTintColor = UIColor(red:133.0/255, green:182.0/255, blue:189.0/255, alpha:1.0)
let toolBar = self.navigationController?.toolbar
toolBar?.barTintColor = UIColor(red:231/255, green:111/255, blue:19.0/255, alpha:1.0)
toolBar?.tintColor = UIColor.blackColor()
我是否也应该将此代码包装在主队列中?
在我的 tableView cellForRowAtIndexPath 函数中,我是否也应该包装所有设置主队列中每个 table 单元格的 UI 的代码?
当我呈现一个新的模态控制器(self.presentViewController(modalController,animated:true,completion:nil)时,我应该将它包装在主队列中吗?
你所有问题的答案是"no"
除非文档中指定,否则所有 UIKit 函数都将在主队列上调用。
通常,在调用异步函数后,您需要在主队列上专门 运行 完成处理程序 运行 在后台队列上。像……
// downloadImage is some func where the
// completion handler runs on a background queue
downloadImage(completion: { image in
DispatchQueue.main.async {
self.imageView.image = image
}
})
是的,只有在后台队列上已经异步执行某个函数时,您才应该调用主队列。而这往往不会自行发生。
正如 Ashley 所说,UIKit 方法会自动从主队列中调用——它们就是这样。那么按理说,有些框架有自动从后台队列调用的方法。
我知道 URLSession 的 dataTask 的 resume 函数会自动在后台队列上执行(这样应用程序就不会因网络连接而变慢),这意味着完成处理程序之后执行也适用于后台队列。这就是为什么在完成处理程序中发生的任何 UI 更新 当然需要 对主队列的调用。
let dataTask = URLSession.shared.dataTask(with: request) {
// begin completion handler
(data, response, error) in
guard error == nil else { print("error \(error.debugDescription)"); return }
guard let data = data else { print("no data"); return }
do {
if let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [[String: Any]] {
print("sending returned JSON to handler")
self.responseHandler.handleAPIResponse(jsonArray: json)
>>>> DispatchQueue.main.async { <<<<
self.tableView.reloadData()
}
}
} catch {
print("get tasks JSONSerialization error")
}
}
dataTask.resume()