完整详解GCD系列(二)dispatch_after;dispatch_apply;dispatch_once
原创Blog,转载请注明出处
本文阅读的过程中,如有概念不懂,请参照前专栏中之前的文章,如果还有疑惑,请留言。
这是我关于GCD专栏的地址
http://blog.csdn.net/column/details/swift-gcd.html
一、dispatch_after
二、dispatch_apply
三、dispatch_once
一、dispatch_after
功能:延迟一段时间把一项任务提交到队列中执行,返回之后就不能取消
常用来在在主队列上延迟执行一项任务
函数原型
func dispatch_after(_ when: dispatch_time_t, _ queue: dispatch_queue_t!, _ block: dispatch_block_t!)参数
when 过了多久执行的时间间隔 queue 提交到的队列 block 执行的任务
例如:可以利用dispatch_after写一个自己用的Delay函数,delay一段时间在主线程上执行一段代码
func hwcDelay(delay:Double, closure:()->()) { dispatch_after( dispatch_time( DISPATCH_TIME_NOW, Int64(delay * Double(NSEC_PER_SEC)) ), dispatch_get_main_queue(), closure) }
只需要这样使用
hwcDelay(0.5){
//Do everything you want
}
比如,当用户的应用不满足某些我们App需要的条件时候(例如,我们的App需要蓝牙打开),然后在APP启动的时候测到蓝牙Off后,应当给用户一个提示。在view载入完成后,延迟给用户一个提示,也可以给这个提示添加一些动画,要比view在载入完成直接显示提示要有好的多。
举例
在viewLoad后,延迟1s,提示一个alertview
class ViewController: UIViewController{ func hwcDelay(delay:Double, closure:()->()) { dispatch_after( dispatch_time( DISPATCH_TIME_NOW, Int64(delay * Double(NSEC_PER_SEC)) ), dispatch_get_main_queue(), closure) } override func viewDidLoad(){ super.viewDidLoad() hwcDelay(1.0){ var alertview = UIAlertView(title:"Dispatch_after",message:"Message",delegate:self,cancelButtonTitle:"OK") alertview.show() } } override func didReceiveMemoryWarning(){ super.didReceiveMemoryWarning() } }
二、dispatch_apply
功能:把一项任务提交到队列中多次执行,具体是并行执行还是串行执行由队列本身决定.注意,dispatch_apply不会立刻返回,在执行完毕后才会返回,是同步的调用。
func dispatch_apply(_ iterations: UInt, _ queue: dispatch_queue_t!, _ block: ((UInt) -> Void)!)参数
iterations 执行的次数 queue 提交到的队列 block 执行的任务
那么,何时使用这个函数呢?从它的功能不难看出,如果我们可以把不相关的循环提交到后台线程并行执行,并且循环任务调度到后台执行的效率提高,能抵消掉队列调度本身的开销,那么效率会显著提高。
举例
比如我有一个数组,存储了一系列对象,初始化的时候,这些对象都要调用一次某函数来进行相关的计算。这些计算相互没有影响。这时,我们就可以用dispatch_apply来使用异步队列来初始化.这里把这种情况进行简化
class ViewController: UIViewController{ var hwcarray = ["hello","hwc","hellohwc"] override func viewDidLoad(){ super.viewDidLoad() dispatch_apply(3,dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0)){ (index:UInt) -> () in var expObject = self.hwcarray[Int(index)] as NSString NSLog("%d",expObject.length) } NSLog("Dispatch_after is over") } override func didReceiveMemoryWarning(){ super.didReceiveMemoryWarning() } }可以看到,输出是
3 5 8 dispatch_after is over由于这样会阻塞主线程,而下文又与dispatch_apply的执行结果无关,所以可以在异步队列中掉dispatch_apply,然后执行完成后进行通知
class ViewController: UIViewController{ var hwcarray = ["hello","hwc","hellohwc"] override func viewDidLoad(){ super.viewDidLoad() dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0)){ dispatch_apply(3,dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0)){ (index:UInt) -> () in var expObject = self.hwcarray[Int(index)] as NSString NSLog("%d",expObject.length) } NSLog("Dispatch_after in global queue is over") } NSLog("Dispatch_after in main queue is over") } override func didReceiveMemoryWarning(){ super.didReceiveMemoryWarning() } }这样输出为
8 Dispatch_after in main queue is over 3 5 Dispatch_after in global queue is over可以看到,相对主队列(主线程)是异步的,在global队列中是并行执行的
三、dispatch_once
功能:保证在APP运行期间,block中的代码只执行一次
func dispatch_once(_ predicate: UnsafeMutablePointer<dispatch_once_t>,
_ block: dispatch_block_t!)
参数
predicate 用来判断提交的block是否执行完成
block 执行一次的任务
dispatch_once的经典实用场景是单例
单例代码:
class hwcSingleton { var testVariable:Int! func print(){ testVariable = testVariable + 1 println(testVariable) } class var sharedObject: hwcSingleton { struct StaticStruct { static var predicate : dispatch_once_t = 0 static var instance : hwcSingleton? = nil } dispatch_once(&StaticStruct.predicate) { StaticStruct.instance = hwcSingleton() StaticStruct.instance?.testVariable = 10 } return StaticStruct.instance! } }
当然也可以在多线程环境下,保证一段代码只执行一次。
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。