代碼基于swift 4.0受啥。
一、在不需要的時(shí)候invalidate()鸽心。
當(dāng)控制器和timer循環(huán)引用時(shí)滚局,不能將 timer?.invalidate() 放在 deinit 方法中,因?yàn)榭刂破鞑粫?huì)被釋放掉顽频,deinit方法不會(huì)被調(diào)用藤肢。
不需要定時(shí)器的時(shí)候invalidate,例如可以在viewDidDisappear 中釋放掉糯景。因?yàn)門imer會(huì)對(duì)target強(qiáng)引用嘁圈,只有當(dāng)timer被invalidate才會(huì)取消強(qiáng)引用省骂。官方描述:
target
The object to which to send the message specified by aSelector when the timer fires. The timer maintains a strong reference to target until it (the timer) is invalidated.
override func viewDidDisappear(_ animated: Bool) {
timer?.invalidate()
timer = nil
}
override func viewDidLoad() {
super.viewDidLoad()
configureUI()
timer = Timer.scheduledTimer(timeInterval: 2, target: self, selector: #selector(handerTimer), userInfo: nil, repeats: true)
}
@objc func handerTimer() {
print("timer")
}
注:嘗試傳weakSelf Timer.scheduledTimer 的target對(duì)象,還是會(huì)發(fā)生引用循環(huán)最住。因?yàn)門imer 對(duì)target強(qiáng)引用冀宴,強(qiáng)引用一個(gè)weak 變量,對(duì)變量所指的對(duì)象仍然是強(qiáng)引用温学。
//此種方式無(wú)效略贮。
weak var weakSelf = self
timer = Timer.scheduledTimer(timeInterval: 2, target: weakSelf!, selector: #selector(handerTimer), userInfo: nil, repeats: true)
二、在timer初始化的block中弱引用控制器仗岖。(這種方式僅限于@available(iOS 10.0, *))
timer弱引用控制器逃延,那么就不會(huì)造成循環(huán)引用,控制器可以正常的釋放掉轧拄。deinit方法會(huì)調(diào)用揽祥。
var timer: Timer?
deinit {
timer?.invalidate()
timer = nil
}
override func viewDidLoad() {
super.viewDidLoad()
// 下面方法@available(iOS 10.0, *)
timer = Timer.scheduledTimer(withTimeInterval: 2, repeats: true, block: { [weak self] (_) in
self?.handerTimer()
})
}
三、第二種方式只能在iOS10.0上使用檩电。為了兼容以下版本拄丰,封裝一個(gè)block類方法,通過(guò)userInfo傳遞俐末。
self -> timer timer --->self timer弱引用self 不存在循環(huán)引用
Timer 循環(huán)引用自己
override func viewDidLoad() {
super.viewDidLoad()
// [weak self] 不能忘
timer = Timer.xx_scheduledTimer(withTimeInterval: 2, repeats: true, block: { [weak self] (_) in
self?.handerTimer()
})
}
@objc func handerTimer() {
print("timer")
}
// 寫一個(gè)Timer的分類料按。
extension Timer {
//兼容不同版本
class func xx_scheduledTimer(withTimeInterval interval: TimeInterval, repeats: Bool, block: @escaping (Timer) -> Void) -> Timer {
if #available(iOS 10.0, *) {
return Timer.scheduledTimer(withTimeInterval: interval, repeats: repeats, block: block)
}
return scheduledTimer(timeInterval: interval, target: self, selector: #selector(xx_handerTimerAction(_:)), userInfo: Block(block), repeats: true)
}
// 一定要加class。 Timer是類對(duì)象卓箫,只能調(diào)用類方法载矿,不能調(diào)用實(shí)例方法(否則報(bào)錯(cuò):[NSTimer xx_handerTimerAction:]: unrecognized selector sent to class 0x1105c30c0')
@objc class func xx_handerTimerAction(_ sender: Timer) {
if let block = sender.userInfo as? Block<(Timer) -> Void> {
block.type(sender)
}
}
}
//Block模型類
class Block<T> {
let type: T
init(_ type: T) {
self.type = type
}
}