這里運(yùn)用中介者模式的思想,封裝一個(gè)Timer贡避,簡(jiǎn)化其他對(duì)象與timer的交互過(guò)程
創(chuàng)建中介者類(lèi)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() {
//執(zhí)行target的sel方法示启,如果target被釋放居扒,則銷(xiāo)毀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
會(huì)隨著當(dāng)前VC對(duì)象的釋放自動(dòng)銷(xiāo)毀,不會(huì)存在循環(huán)引用問(wèn)題蝌焚,也不用手動(dòng)調(diào)用timer.invalidate()
補(bǔ)充
如果VC沒(méi)有實(shí)現(xiàn)aSelector方法,程序就會(huì)直接崩潰誓斥,我們可以重寫(xiě)RTimer的forwardingTarget
方法只洒,利用消息轉(zhuǎn)發(fā)機(jī)制在崩潰前輸出一些信息
override func forwardingTarget(for aSelector: Selector!) -> Any? {
print(aSelector)
if target?.responds(to: self.sel!) == true {
return target
}
print("\(target)沒(méi)有實(shí)現(xiàn)方法:\(NSStringFromSelector(aSelector))")
return super.forwardingTarget(for: aSelector)
}