iOS 中定时器小记

1.iOS 中定时器的解决方案?

(1).CADisplayLink

使用简单,代码简洁,和屏幕刷帧频率相同,使用时需要注意循环引用问题,由于依赖 RunLoop 来实现定时功能.所以需要手动添加到 RunLoop 中.

(2).NSTimer

NSTimer 是我们项目中经常使用到的定时器的一种方案,同样也需要注意循环引用问题, NSTimer 和CADisplayLink一样,需要依赖 RunLopp,所以也需要手动添加到 RunLoop 中,需要注意的是,使用 NSTimer 的类方法scheduledTimerWithTimeInterval:创建 NSTimer 时,会自动添加到当前的 RunLoop 中.

(3).GCD

C语言的一套实现定时任务的方案,代码相对较多,使用较繁琐

*使用CADisplayLink和NSTimer过程中出现的循环引用的问题可以通过NSProxy来解决

*相对于CADisplayLink和NSTimer, GCD不依赖于 RunLoop, 和系统内核直接挂钩,所以具有更高的准时性,万一 RunLoop 处理的事情很多,就会造成CADisplayLink和NSTimer的不准确.

2.使用GCD简单自定义的定时器

 下面是使用GCD 实现的定时器,可以直接拿来用.

#import

@interfaceMRTimer :NSObject

+(NSString*)doTask:(void(^)(void))task

        start:(NSTimeInterval)start

     interval:(NSTimeInterval)interval

       repeat:(BOOL)repeat

        async:(BOOL)async;

+(NSString*)doTask:(id)target

           selector:(SEL)selector

              start:(NSTimeInterval)start

           interval:(NSTimeInterval)interval

             repeat:(BOOL)repeat

              async:(BOOL)async;

+(void)cancelTask:(NSString*)name;

@end


#import "MRTimer.h"

@implementation MRTimer

static NSMutableDictionary *timers_;

dispatch_semaphore_t semaphore_;

+(void)initialize{

    staticdispatch_once_tonceToken;

    dispatch_once(&onceToken, ^{

        timers_=@{}.mutableCopy;

        semaphore_ = dispatch_semaphore_create(1);

    });

}

+(NSString*)doTask:(void(^)(void))task

        start:(NSTimeInterval)start

     interval:(NSTimeInterval)interval

       repeat:(BOOL)repeat

        async:(BOOL)async{


    if(!task || start <0|| (interval <=0&& repeat))returnnil;


    dispatch_queue_tqueue = async

    ?dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)

    :dispatch_get_main_queue();

    dispatch_source_ttimer =dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER,0,0, queue);

    dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, start * NSEC_PER_SEC, interval * NSEC_PER_SEC);

    dispatch_semaphore_wait(semaphore_, DISPATCH_TIME_FOREVER);

    NSString*name = [NSStringstringWithFormat:@"%lu",(unsignedlong)timers_.count];

    timers_[name] = timer;

    dispatch_semaphore_signal(semaphore_);

    dispatch_source_set_event_handler(timer, ^{

        task();

        if(!repeat) {

            dispatch_source_cancel(timer);

        }

    });

    dispatch_resume(timer);


    returnname;

}

+(NSString*)doTask:(id)target

           selector:(SEL)selector

              start:(NSTimeInterval)start

           interval:(NSTimeInterval)interval

             repeat:(BOOL)repeat

              async:(BOOL)async{

    if(!target || !selector)returnnil;

    return [self doTask:^{

        if([targetrespondsToSelector:selector]) [targetperformSelector:selector];

    }start:startinterval:intervalrepeat:repeatasync:async];

}

+(void)cancelTask:(NSString*)name{

    if(name.length==0)return;

    dispatch_semaphore_wait(semaphore_, DISPATCH_TIME_FOREVER);


    dispatch_source_ttimer =timers_[name];


    if(!timer)return;


    dispatch_source_cancel(timer);

    [timers_ removeObjectForKey:name];


    dispatch_semaphore_signal(semaphore_);


}

@end

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容