iOS开发

iOS开发 计时器的实现方式

2017-10-14  本文已影响81人  superDg

iOS中计时器常用的有两种方式

使用NSTimer类(Swift 中更名为 Timer)

NSTimer 常用的初始化方法区别

方法一

objc
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)yesOrNo;
swift
class func scheduledTimer(timeInterval ti: TimeInterval, target aTarget: Any, selector aSelector: Selector, userInfo: Any?, repeats yesOrNo: Bool) -> Timer

方法二

objc
+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)yesOrNo;
swift
init(timeInterval ti: TimeInterval, target aTarget: Any, selector aSelector: Selector, userInfo: Any?, repeats yesOrNo: Bool)

方法三 需要iOS 10以上

objc
+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)interval repeats:(BOOL)repeats block:(void (^)(NSTimer *timer))block;
swift
init(timeInterval interval: TimeInterval, repeats: Bool, block: @escaping (Timer) -> Void)

方法四 需要iOS 10以上

objc
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)interval repeats:(BOOL)repeats block:(void (^)(NSTimer *timer))block;
swift
class func scheduledTimer(withTimeInterval interval: TimeInterval, repeats: Bool, block: @escaping (Timer) -> Void) -> Timer

注释

Timer 内存管理

Timer对参数的引用都是强引用,而且添加到RunLoop中也是强引用。在ViewController中,controller持有timerRunLoop持有timer,一般在dealloc中调用timer.invalidate,但是此时RunLoop仍然持有timer,并不会走dealloc,导致ViewController无法释放。要求不要的可以在viewWillDisappear:中调用timer.invalidate。这也只能在当前页面使用定时器,离开了这个页面就不行了。网上有折中的方法就是ViewController不持有timer,借助单例类来实现,这只能算折中的方法。在下方补充中有一种解决方案。

使用GCD

GCD在swift3以后改动很大,所以分开来说

objc

uint64_t interval = 5 * NSEC_PER_SEC;
//创建一个专门执行timer回调的GCD队列
dispatch_queue_t queue = dispatch_queue_create("timerQueue", 0);
_timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
//使用dispatch_source_set_timer函数设置timer参数
dispatch_source_set_timer(_timer, dispatch_time(DISPATCH_TIME_NOW, 0), interval, 0);
//设置回调

__weak __typeof(self) ws = self
dispatch_source_set_event_handler(_timer, ^(){ [ws sendRequest]; });
dispatch_resume(_timer);
dealloc方法
- (void)dealloc
{
if (_timer != NULL) {
dispatch_cancel(_timer);
_timer = NULL;
}
}

swift

var ti : DispatchSourceTimer!
ti = DispatchSource.makeTimerSource(flags:DispatchSource.TimerFlags.init(rawValue: 0) , queue: nil);
ti.schedule(deadline: DispatchTime.now(), repeating: 2.0)
ti.setEventHandler { [weak self] in self?.timerAction() }
ti.resume()
deinit { if ti != nil { ti.suspend() } }

总结

如果在一个页面里面需要使用定时器,离开页面就停止,个人倾向于使用NSTimer类实现。如果离开页面不能停止还需要继续执行,使用GCD好一点吧,毕竟不会出现内存问题。折中的方法个人是不喜欢的。大家在项目中一定要具体问题具体对待,实现方法有很多,选择自己认为比较好的,没有问题的才是正确的。

补充 2017-12-19

上一篇 下一篇

猜你喜欢

热点阅读