iOS倒计时的探究与选择

本文探讨了iOS开发中实现倒计时的四种常见方法:PerformSelector、NSTimer、CADisplayLink和GCD。分别介绍了它们的工作原理、优缺点以及可能遇到的精度和内存管理问题。对于需要高精度倒计时的场景,推荐使用GCD。文章还提供了实际应用场景的实践案例,如轮播图、FPS检测和活动倒计时等。
摘要由CSDN通过智能技术生成

我们在开发应用的过程中,往往在很多地方需要倒计时,比如说轮播图,验证码,活动倒计时等等。而在实现这些功能的时候,我们往往会遇到很多坑需要我们小心的规避掉。
因为文章内容的关系,要求大家都有一些runloop的基础知识,当然如果没有,也没什么特别大的问题。这里推荐一下 ibireme的这篇文章。

话不多说,直接上正题:

倒计时的种类

在开发过程中,我们基本上只用了这几种方式来实现倒计时

1.PerformSelecter
2.NSTimer
3.CADisplayLink
4.GCD

PerformSelecter

我们使用下面的代码可以实现指定延迟之后执行:

- (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay;

它的方法描述如下

Invokes a method of the receiver on the current thread using the default mode after a delay.
This method sets up a timer to perform the aSelector message on the current thread’s run loop. The timer is configured to run in the default mode (NSDefaultRunLoopMode). When the timer fires, the thread attempts to dequeue the message from the run loop and perform the selector. It succeeds if the run loop is running and in the default mode; otherwise, the timer waits until the run loop is in the default mode.
If you want the message to be dequeued when the run loop is in a mode other than the default mode, use the performSelector:withObject:afterDelay:inModes: method instead. If you are not sure whether the current thread is the main thread, you can use the performSelectorOnMainThread:withObject:waitUntilDone: or performSelectorOnMainThread:withObject:waitUntilDone:modes:method to guarantee that your selector executes on the main thread. To cancel a queued message, use the cancelPreviousPerformRequestsWithTarget: or cancelPreviousPerformRequestsWithTarget:selector:object:method.

这个方法在Foundation框架下的NSRunLoop.h文件下。当我们调用NSObject 这个方法的时候,在runloop的内部是会创建一个Timer并添加到当前线程的 RunLoop 中。所以如果当前线程没有 RunLoop,则这个方法会失效。而且还有几个很大的缺陷:

  • 这个方法必须在NSDefaultRunLoopMode下才能运行

  • 因为它基于RunLoop实现,所以可能会造成精确度上的问题。
    这个问题在其他两个方法上也会出现,所以我们下面细说

  • 内存管理上非常容易出问题。
    当我们执行 [self performSelector: afterDelay:]的时候,系统会将self的引用计数加1,执行完这个方法时,还会将self的引用计数减1,当方法还没有执行的时候,要返回父视图释放当前视图的时候,self的计数没有减少到0,而导致无法调用dealloc方法,出现了内存泄露。

因为它有如此之多的缺陷,所以我们不应该使用它,或者说,不应该在倒计时这方法使用它。

NSTimer

+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti invocation:(NSInvocation *)invocation repeats:(BOOL)yesOrNo;
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti invocation:(NSInvocation *)invocation repeats:(BOOL)yesOrNo;
+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(nullable id)userInfo repeats:(BOOL)yesOrNo;
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(nullable id)userInfo repeats:(BOOL)yesOrNo;
+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)interval repeats:(BOOL)repeats block:(void (^)(NSTimer *timer))block API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0));
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)interval repeats:(BOOL)repeats block:(void (^)(NSTimer *timer))block API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0));

方法描述如下

A timer that fires after a certain time interval has elapsed, sending a specified message to a target object.
Timers work in conjunction with run loops. Run loops maintain strong references to their timers, so you don’t have to maintain your own strong reference to a timer after you have added it to a run loop.
To use a timer effectively, you should be aware of how run loops operate. See Threading Programming Guide for more information.
A timer is not a real-time mechanism. If a timer’s firing time occ

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值