这里运用中介者模式的思想,封装一个Timer,简化其他对象与timer的交互过程
创建中介者类RTimer
var timer: Timer?
weak var target: NSObjectProtocol?
var sel: Selector?
func scheduled(timeInterval ti: TimeInterval, target aTarget: Any, selector aSelector: Selector, userInfo: Any?, repeats yesOrNo: Bool) {
self.target = aTarget as? NSObjectProtocol
self.sel = aSelector
timer = Timer(timeInterval: ti, target: self, selector: aSelector, userInfo: userInfo, repeats: yesOrNo)
RunLoop.current.add(timer!, forMode: .common)
guard self.target?.responds(to: self.sel!) == true else {
return
}
//交换方法
let method = class_getInstanceMethod(self.classForCoder, #selector(fire))
class_replaceMethod(self.classForCoder, self.sel!, method_getImplementation(method!), method_getTypeEncoding(method!))
}
@objc func fire() {
//执行target的sel方法,如果target被释放,则销毁timer
if self.target?.perform(self.sel!) == nil {
timer?.invalidate()
}
}
timer
的使用
//VC:
rTimer.scheduled(timeInterval: 1, target: self, selector: #selector(timerFire), userInfo: nil, repeats: true)
rTimer
会随着当前VC对象的释放自动销毁,不会存在循环引用问题,也不用手动调用timer.invalidate()
补充
如果VC没有实现aSelector方法,程序就会直接崩溃,我们可以重写RTimer的forwardingTarget
方法,利用消息转发机制在崩溃前输出一些信息
override func forwardingTarget(for aSelector: Selector!) -> Any? {
print(aSelector)
if target?.responds(to: self.sel!) == true {
return target
}
print("\(target)没有实现方法:\(NSStringFromSelector(aSelector))")
return super.forwardingTarget(for: aSelector)
}