【问题标题】:Swift Timer Target To Prevent Retain Cycle快速计时器目标以防止保留周期
【发布时间】:2021-04-10 01:11:38
【问题描述】:

在iOS 10之前,直接使用Timer会产生Retain Cycle,所以我使用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)
}

【问题讨论】:

  • 真的不需要class_getMethodImplementation等所有这些。如果存在保留循环的危险,请打破它。
  • 有一个基于闭包的 Timer API,你为什么不直接使用它呢?

标签: swift timer crash


【解决方案1】:

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

  • 模拟系统的关闭
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
      })
}
  • DispatchSource 替换 Timer
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()
}

  • NSProxy

【讨论】:

  • 这是不必要的详尽。在 iOS 10 之前,我们都在使用 Timer / NSTimer,避免保留循环很简单。您只需在deinit 之前的某个时间invalidate 计时器(例如viewWillDisappear)。确实,一个不错的替代方案是 DispatchSource 计时器,但您仍然必须取消计时器。见我的github.com/mattneub/Programming-iOS-Book-Examples/blob/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-08-20
  • 2014-05-09
  • 1970-01-01
  • 2016-04-02
  • 2021-06-30
  • 2018-07-02
  • 2016-12-04
相关资源
最近更新 更多