Swift 快速定时器目标,以防止保留周期
在ios10之前,直接使用计时器将生成retaincycle,所以我使用Runtime来构建代码,但代码在构建时崩溃。我不知道空指针是在哪里生成的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) {
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()
}