DevQiao Keep on hacking

iOS多线程-GCD使用指南

最近的计步器App涉及异步API,我开始试图将CMPedometer的查询方法封装为一个函数,这个函数可以返回 查询方法得到的结果,方便使用。然而事实却没有这么简单,由于查询方法是异步API,因此只要调用该方法 操作就会被分配到另一个线程去做,因此当查询到结果后,调用这个查询方法的方法早已执行完毕,因此返回空, 也就是除了查询方法自带的回调block中可以取到查询结果,其他地方没法获取查询结果。

  // stepsInToday永远取不到值
  func queryPedometerTodayTotalData() -> Int {
       var stepsInToday = 0
       self.queryPedometerDataFromDate(NSDate.today()!, toDate: NSDate()) {
           (pedometerData, error) in
           stepsInToday = (pedometerData?.numberOfSteps.integerValue)!
       }
       return stepsInToday
   }

期间试过给 NSOperation 添加依赖,或者使用 dispatch_group_async,但是用这些方法解决异步API 都不奏效,因为异步API操作始终会分去别的线程处理, 我开始的解决办法是在返回前阻塞等待一段时间(如2秒),这样就解决了时序问题,但是这种方式并不好, 试想如果硬件原因(也可能网络应用相关的延迟)超过这个时间段(2秒),则应用崩溃

  // 通过延时执行的解决方法
  func queryPedometerTodayTotalData() -> Int {
       var stepsInToday = 0
       self.queryPedometerDataFromDate(NSDate.today()!, toDate: NSDate()) {
           (pedometerData, error) in
           stepsInToday = (pedometerData?.numberOfSteps.integerValue)!
       }

       sleep(2) //用于阻塞线程

       return stepsInToday
   }

今天突然看到一篇博文,恍然大悟,解决了困惑已久的问题

//通过信号量机制阻塞线程的解决办法
//注:这个方法会阻塞当前线程,因此应该异步调用,后台让后台线程阻塞无妨
func queryPedometerTodayTotalData() -> Int {
    var stepsInToday = 0
    let semaphore = dispatch_semaphore_create(0)
    self.queryPedometerDataFromDate(NSDate.today()!, toDate: NSDate()) {
        (pedometerData, error) in
        stepsInToday = (pedometerData?.numberOfSteps.integerValue)!
        dispatch_semaphore_signal(semaphore)
    }
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)
    return stepsInToday
}

至此对GCD有了进一步认识,结合这篇博文总结一下:

GCD使用指南

后台执行

  let defaultPriority = DISPATCH_QUEUE_PRIORITY_DEFAULT  //该优先级最常用
  let backgroundQueue = dispatch_get_global_queue(defaultPriority, 0) //返回并发队列
  dispatch_async(backgroundQueue, {
    let result = doSomeExpensiveWork()
    dispatch_async(dispatch_get_main_queue(), {
      //使用 `result` 做各种事
    })
  })

创建单例

摊平 completion block

限制并发的数量

等待许多并发任务完成

隔离队列

总结

GCD 是一个具备底层特性的框架,通过它,我们可以构建高层级的抽象行为。这篇文章较为全面的讲述了 GCD 的相关应用领域,对iOS多线程有了更进一步的认识,其中很多内容还只停留在概念层面,待以后实际运用到再深入理解。

comments powered by Disqus