創建一個NSTimer,有多種方法,如
scheduledTimerWithTimeInterval:target:selector:userInfo:repeats:
timerWithTimeInterval:target:selector:userInfo:repeats:
等等
其中,用不帶有scheduled
的,在初始化了后,還需要調用
addTimer:forMode:
方法,將Timer加入到runloop中。
參數:
-
seconds
定時時間 -
target
發送對象 -
aSelector
定時器啟動調用的方法 -
userInfo
可為nil,使用者的信息 -
repeats
定時器是否循環
在Timer添加到runloop后,定時器立刻啟動,在seconds時間后,調用aSelector
方法,如果最開始時不想等seconds時間,可調用-fire方法,立刻調用aSelector
方法。
-invalidate
方法可使定時器失效。
注意:
- 使用
-invalidate
方法后,即使再次使用-fire方法也不會讓定時器再次工作,因為-invalidate
方法是使Timer失效。 - 暫停定時器:可使用
[self setFireDate:[NSDate distantFuture]];
方法:即將定時器啟動時間設為無窮遠
恢復定時器,使用[self setFireDate:[NSDate date]];
方法:即將定時器啟動時間設為現在的時刻。 - 對于需要在暫停時刻改變定時時間間隔的情況,則需要重新創建NSTImer,啟動,通過-invalidate停止定時器。
NSTimer 內存泄漏解決方法
由于 NSTimer
容易與持有它的對象互相引用,從而導致內存泄漏,因此在使用時需要格外注意。 iOS 10.0 以后已經有了 scheduledTimer(withTimeInterval:repeats:block:)
方法解決內存泄漏問題,但是 iOS 10.0 以前還需要自己想辦法。
- 如果
timerWithTimeInterval:target:selector:userInfo:repeats:
中傳給 target 的為weakSelf
是否可以?
不可以。因為 Timer 對 target 強引用,強引用一個 weak 變量,對變量所指的對象仍然是強引用 - 借鑒參考 1 中第 52 條的方法解決該問題。
extension Timer {
class func njyScheduledTimer(timerInterval: TimeInterval, block: @escaping () -> Void, repeats: Bool) -> Timer {
return Timer.scheduledTimer(timeInterval: timerInterval, target: self, selector: #selector(njyBlockInvoke(timer:)), userInfo: [block copy], repeats: repeats)
}
@objc class func njyBlockInvoke(timer: Timer) {
let block = timer.userInfo as? () -> Void
if let block = block {
block()
}
}
}
注意:在實際使用時,仍然要注意內存泄漏的問題,因此需要使用 weak var weakSelf = self
和 let strongSelf = weakSelf
打破保留環,解決內存泄漏的問題。