Swift 快速定时器目标,以防止保留周期

Swift 快速定时器目标,以防止保留周期,swift,timer,crash,Swift,Timer,Crash,在ios10之前,直接使用计时器将生成retaincycle,所以我使用Runtime来构建代码,但代码在构建时崩溃。我不知道空指针是在哪里生成的 var time: Timer? var target: NSObject? target = NSObject() let selector = #selector(timePrint) if let method = class_getMethodImplementation(self.classForCoder, selector) {

在ios10之前,直接使用计时器将生成retaincycle,所以我使用Runtime来构建代码,但代码在构建时崩溃。我不知道空指针是在哪里生成的

var time: Timer?
var target: NSObject?


target = NSObject()
let selector = #selector(timePrint)
if let method = class_getMethodImplementation(self.classForCoder, selector) {
     let IMP = method_getImplementation(method)
     let encodeing = method_getTypeEncoding(method)
     class_addMethod(target?.classForCoder, selector, IMP, encodeing)
     time = Timer.scheduledTimer(timeInterval: 2, target: target!, selector: selector, userInfo: nil, repeats: true)
}

因为我想与iOS 10之前的旧版本兼容。所以我只能这样做。目前已知的方法如下:

  • 模拟系统的关闭
  • DispatchSource以替换计时器
  • NSProxy

确实不需要所有这些
class_getMethodImplementation
等。如果存在保留周期的危险,请打破它。有一个基于闭包的计时器API,为什么不直接使用它呢?这是不必要的详细说明。在iOS 10之前,我们都使用Timer/NSTimer,避免保留周期很简单。您只需在
deinit
之前的某个时间
使计时器失效即可(例如
视图将消失
)。的确,一个不错的替代方案是DispatchSource计时器,但您仍然必须取消计时器。看我的
extension Timer {
    class func rp_scheduledTimer(timeInterval ti: TimeInterval, repeats yesOrNo: Bool, closure: @escaping (Timer) -> Void) -> Timer {
        return self.scheduledTimer(timeInterval: ti, target: self, selector: #selector(RP_TimerHandle(timer:)), userInfo: closure, repeats: yesOrNo)
}
    
    @objc class func RP_TimerHandle(timer: Timer) {
        var handleClosure = { }
        handleClosure = timer.userInfo as! () -> ()
        handleClosure()
    }
}
if #available(iOS 10.0, *) {
      time = Timer.scheduledTimer(withTimeInterval: 2, repeats: true, block: { [weak self] (timer) in
            // do something
      })
} else {
      time = Timer.rp_scheduledTimer(timeInterval: 2, repeats: true, closure: { [weak self] (timer) in
            // do something
      })
}
var source: DispatchSourceTimer?

if #available(iOS 10.0, *) {

} else {

   source = DispatchSource.makeTimerSource(flags: [], queue: .global())
   source.schedule(deadline: .now(), repeating: 2)
   source.setEventHandler {
       // do something...
   }
   source.resume()
}