GCD 閱讀

Swift Tips GCD 延時調用

一般使用GCD方式
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 创建目标队列
let workingQueue = dispatch_queue_create("my_queue", nil)

// 派发到刚创建的队列中,GCD 会负责进行线程调度
dispatch_async(workingQueue) {
// 在 workingQueue 中异步进行
println("努力工作")
NSThread.sleepForTimeInterval(2) // 模拟两秒的执行时间

dispatch_async(dispatch_get_main_queue()) {
// 返回到主线程更新 UI
println("结束工作,更新 UI")
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import Foundation

typealias Task = (cancel : Bool) -> ()

func delay(time:NSTimeInterval, task:()->()) -> Task? {

func dispatch_later(block:()->()) {
dispatch_after(
dispatch_time(
DISPATCH_TIME_NOW,
Int64(time * Double(NSEC_PER_SEC))),
dispatch_get_main_queue(),
block)
}

var closure: dispatch_block_t? = task
var result: Task?

let delayedClosure: Task = {
cancel in
if let internalClosure = closure {
if (cancel == false) {
dispatch_async(dispatch_get_main_queue(), internalClosure);
}
}
closure = nil
result = nil
}

result = delayedClosure

dispatch_later {
if let delayedClosure = result {
delayedClosure(cancel: false)
}
}

return result;
}

func cancel(task:Task?) {
task?(cancel: true)
}
調用方式
1
2
3
4
5
let task = delay(5) { println("拨打 110") }

// 仔细想一想..
// 还是取消为妙..
cancel(task)

swift GCD使用指南

Dispatch Queue

  • Serial Dispatch Queue,FIFO(先進先出),一次只能執行一個
  • Concurrent Dispatch Queue,并发执行队列里的任务

Queue Types (型態dispatch_queue_t)

  • Main queue(Serial Queue) dispatch_get_main_queue()
  • Global Dispatch Queues(Concurrent Queue)
    • high dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH,0)
    • default dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0)
    • low dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW,0)
    • background dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND,0)
  • 自訂
    • Serial dispatch_queue_create("com.xxx", DISPATCH_QUEUE_SERIAL)
    • Concurrent dispatch_queue_create("com.xxx", DISPATCH_QUEUE_CONCURRENT)
1
2
3
4
5
6
7
8
9
10
dispatch_queue_t low = dispatch_queue_create("low",DISPATCH_QUEUE_SERIAL);
dispatch_queue_t high = dispatch_queue_create("high",DISPATCH_QUEUE_SERIAL);
dispatch_set_target_queue(low,high);

dispatch_async(low,^{});

dispatch_suspend(low);
dispatch_async(high,^{
dispatch_resume(low);
});//跟retain release一樣,suspend resume次數要成對

丟入GCD的任務無法取消
dispatch_after 是指過一段時間之後把任務丟入GCD因此可以抽回

Dispatch Group

執行續1 和 執行續2 皆執行完畢後,執行彙總結果區塊
1
2
3
4
5
6
7
8
9
10
11
12
13
14
dispatch_group_t group = dispatch_group_create();
dispatch_group_async(group, dispatch_get_global_queue(0,0), ^{
// 并行执行的线程一
});
dispatch_group_async(group, dispatch_get_global_queue(0,0), ^{
// 并行执行的线程二
});
dispatch_group_notify(group, dispatch_get_global_queue(0,0), ^{
// 汇总结果
});

//使用dispatch_group_wait函数
//dispatch_group_wait(group, DISPATCH_TIME_FOREVER)
//這種寫法也可以等到group內的任務完成,不過是block形式

WWDC 2014 QoS

  • It is recommended to use quality of service class values to identify the
  • well-known global concurrent queues:
    • QOS_CLASS_USER_INTERACTIVE
    • QOS_CLASS_USER_INITIATED
    • QOS_CLASS_DEFAULT
    • QOS_CLASS_UTILITY
    • QOS_CLASS_BACKGROUND
      *
  • The global concurrent queues may still be identified by their priority,
  • which map to the following QOS classes:
    • DISPATCH_QUEUE_PRIORITY_HIGH: QOS_CLASS_USER_INITIATED
    • DISPATCH_QUEUE_PRIORITY_DEFAULT: QOS_CLASS_DEFAULT
    • DISPATCH_QUEUE_PRIORITY_LOW: QOS_CLASS_UTILITY
    • DISPATCH_QUEUE_PRIORITY_BACKGROUND: QOS_CLASS_BACKGROUND