队列中追加了一项任务并立即返回了。这项任务会在GCD决定的稍后时间执行。当你需要执行网络请求或在后台执行繁重的CPU任务时,使用dispatch_async不会阻塞当前进程。
何 时使用何种队列类型快速指南: – 自定义顺序队列:当你想顺序执行后台任务并追踪它时,这是一个很好的选择。因为同时只有一个任务在执行,因此消除了资源竞争。注意如果需要从方法中获取数 据,你必须内置另一个闭包来得到它或者考虑使用dispatch_sync。 – 主队列(顺序):当并发队列中的任务完成需要更新UI的时候,这是一个通常的选择。为达此目的,需要在一个闭包中嵌入另一个闭包。同时,如果在主队列中调 用dispatch_async来返回主队列,能保证新的任务会在当前方法完成后再执行。 – 并发队列:通常用来执行与UI无关的后台任务。
获取全局队列的帮助变量(Helper Variable)
你 可能注意到dispatch_get_global_queue的QoS等级参数写起来有些繁琐。这是由于qos_class_t被定义为一个结构体,它 包含有Uint32型的属性value,而这个属性需要被转型为Int。在Utils.swift中添加一些全局的计算变量,使获取全局队列更方便一些:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
var
GlobalMainQueue: dispatch_queue_t {
return
dispatch_get_main_queue()
}
var
GlobalUserInteractiveQueue: dispatch_queue_t {
return
dispatch_get_global_queue(Int(QOS_CLASS_USER_INTERACTIVE.value), 0)
}
var
GlobalUserInitiatedQueue: dispatch_queue_t {
return
dispatch_get_global_queue(Int(QOS_CLASS_USER_INITIATED.value), 0)
}
var
GlobalUtilityQueue: dispatch_queue_t {
return
dispatch_get_global_queue(Int(QOS_CLASS_UTILITY.value), 0)
}
var
GlobalBackgroundQueue: dispatch_queue_t {
return
dispatch_get_global_queue(Int(QOS_CLASS_BACKGROUND.value), 0)
}
|
回到PhotoDetailViewController中的viewDidLoad中,将dispatch_get_global_queue和dispatch_get_main_queue替换为帮助变量:
1
2
3
4
5
6
|
dispatch_async(GlobalUserInitiatedQueue) {
let overlayImage = self.faceOverlayImageFromImage(self.image)
dispatch_async(GlobalMainQueue) {
self.fadeInNewImage(overlayImage)
}
}
|
这使得调度调用更易读并且很容易看出在使用哪个队列。
用dispatch_after推迟任务
仔细思考你的app中的UX。用户可能在第一次打开app的时候不知道该做什么,不是吗?
如果在PhotoManager类中没有图片的时候,给用户一个提示是个不错的主意。然而,你同时要考虑用户的视线怎样扫过屏幕:如果提示出现的太快,用户可能还在看其他的地方而忽略了提示。
推迟一秒钟再出现提示,此时便可抓住用户的注意力,因为他们已经对app有了第一印象。
将下面的代码加到showOrHideNavPrompt的实现中,它位于PhotoCollectionViewController.swift文件底部。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
func showOrHideNavPrompt() {
let delayInSeconds = 1.0
let popTime = dispatch_time(DISPATCH_TIME_NOW,
Int64(delayInSeconds * Double(NSEC_PER_SEC)))
// 1
dispatch_after(popTime, GlobalMainQueue) {
// 2
let count = PhotoManager.sharedManager.photos.count
if
count > 0 {
self.navigationItem.prompt = nil
  |