问题描述
@objc public extension RCTTouchHandler {
static let kSessionTimer = "sessionTimer"
var sessionTimer: Timer {
get {
return objc_getAssociatedobject(self,RCTTouchHandler.kSessionTimer) as? Timer ?? Timer.scheduledTimer(timeInterval: RCTTouchHandler.kSessionExpiredDuration,target: self,selector: #selector(touchSessionExpiration),userInfo: nil,repeats: false)
}
set(timer) {
objc_setAssociatedobject(self,RCTTouchHandler.kSessionTimer,self,.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
@objc func touchSessionExpiration() {
print("session expired")
}
deinit {
self.sessionTimer.invalidate()
}
}
那么,sessionTimer
对这个对象有强引用,同时这个对象强保留sessionTimer
。为了避免保留周期和内存泄漏,我应该在对象被取消初始化时使计时器无效。但是,在尝试使此扩展中的 deinit 函数中的计时器无效时,我遇到了以下错误。
Deinitializers may only be declared within a class
扩展可以向类添加新的便利初始化器,但不能向类添加新的指定初始化器或析构器。指定的初始化器和析构器必须始终由原始类实现提供。
所以我想知道如何在此扩展中正确地使计时器无效?
解决方法
如您所说,您不能在扩展中实现 deinit { }
。
您可以创建自己的对象并在那里实现 deinit { }
,而不是在任何地方使用 RCTTouchHandler
,而是使用您自己的对象:
@objc extension RCTTouchHandler {
static let kSessionTimer = "sessionTimer"
}
public class MyTouchHandler: RCTTouchHandler {
private var timer: Timer? = nil
var sessionTimer: Timer {
get {
guard let timer = timer else {
let newTimer = Timer.scheduledTimer(timeInterval: RCTTouchHandler.kSessionExpiredDuration,target: self,selector: #selector(touchSessionExpiration),userInfo: nil,repeats: false)
self.timer = newTimer
return newTimer
}
return timer
}
set(timer) {
self.timer = timer
}
}
@objc func touchSessionExpiration() {
print("session expired")
}
deinit {
self.timer?.invalidate()
}
}