1. 程式人生 > 程式設計 >Swift4使用GCD實現計時器

Swift4使用GCD實現計時器

開發過程中,我們可能會經常使用到計時器。蘋果為我們提供了Timer。但是在平時使用過程中會發現使用Timer會有許多的不便

1:必須保證在一個活躍的runloop,我們知道主執行緒的runloop是活躍的,但是在其他非同步執行緒runloop就需要我們自己去開啟,非常麻煩。
2:Timer的建立和銷燬必須在同一個執行緒。跨執行緒就操作不了
3:記憶體問題。可能迴圈引用造成記憶體洩露

由於存在上述問題,我們可以採用GCD封裝來解決。

import UIKit
typealias ActionBlock = () -> ()

class MRGCDTimer: NSObject {
  
  static let share = MRGCDTimer()
  
  lazy var timerContainer = [String : DispatchSourceTimer]()
  
  
  /// 建立一個名字為name的定時
  ///
  /// - Parameters:
  ///  - name: 定時器的名字
  ///  - timeInterval: 時間間隔
  ///  - queue: 執行緒
  ///  - repeats: 是否重複
  ///  - action: 執行的操作
  func scheduledDispatchTimer(withName name:String?,timeInterval:Double,queue:DispatchQueue,repeats:Bool,action:@escaping ActionBlock ) {
    if name == nil {
      return
    }
    var timer = timerContainer[name!]
    if timer==nil {
      timer = DispatchSource.makeTimerSource(flags: [],queue: queue)
      timer?.resume()
      timerContainer[name!] = timer
    }
    timer?.schedule(deadline: .now(),repeating: timeInterval,leeway: .milliseconds(100))
    timer?.setEventHandler(handler: { [weak self] in
      action()
      if repeats==false {
        self?.destoryTimer(withName: name!)
      }
    })
    
  }
  
  
  /// 銷燬名字為name的計時器
  ///
  /// - Parameter name: 計時器的名字
  func destoryTimer(withName name:String?) {
    let timer = timerContainer[name!]
    if timer == nil {
      return
    }
    timerContainer.removeValue(forKey: name!)
    timer?.cancel()
  }
  
  
  /// 檢測是否已經存在名字為name的計時器
  ///
  /// - Parameter name: 計時器的名字
  /// - Returns: 返回bool值
  func isExistTimer(withName name:String?) -> Bool {
    if timerContainer[name!] != nil {
      return true
    }
    return false
  }

}

使用方法

MRGCDTimer.share.scheduledDispatchTimer(withName: "name",timeInterval: 1,queue: .main,repeats: true) {
   //code
    self.updateCounter()
 }

取消計時器

MRGCDTimer.share.destoryTimer(withName: "name")

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。