NSTimer

1、常规使用

  • 1.1 不会阻塞主线程。

- (NSTimer *)heartTimer {
    if (!_heartTimer) {
        // scheduledTimer创建的定时器,默认添加到当前当前RunLoop的NSDefaultRunLoopMode模式下
        _heartTimer = [NSTimer scheduledTimerWithTimeInterval:3
                                                        target:self
                                                      selector:@selector(heartTask)
                                                      userInfo:nil
                                                       repeats:YES];
        // 修改模式
        [[NSRunLoop currentRunLoop] addTimer:_heartTimer forMode:NSRunLoopCommonModes];
    }
    return _heartTimer;
}

- (void)heartTask {

}
  • 1.2 启动与暂停

- (void)restartTimer {
    [self.heartTimer setFireDate:[NSDate distantPast]];
}

- (void)pauseTimer {
    [self.heartTimer setFireDate:[NSDate distantFuture]];
}
  • 1.3 不使用时要销毁
- (void)dealloc {
    [self.timer invalidate];
    self.timer = nil;
}

2、子线程定时器的创建

  • 在子线程创建定时器时,需要手动开启子线程的运行循环。
dispatch_async(dispatch_get_global_queue(0, 0), ^{

	// 在子线程创建定时器
	/*
	scheduled 或 timer 方式创建
	*/
	self.timer = [NSTimer timerWithTimeInterval:1.0 
	target:self 
	selector:@selector(updateTimer:) 
	userInfo:nil 
	repeats:YES];            
	[[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSDefaultRunLoopMode];

	// 启动子线程的运行循环
	/*
	这句代码就是一个死循环!如果不停止运行循环,不会执行添加到此句之后的任何代码
	*/
	CFRunLoopRun();

	// 停止子线程运行循环之前,不会执行添加到此处的任何代码
});
// 定时器执行操作方法

- (void)updateTimer {
	static int num = 0;
	num++;
	// 满足条件后,停止当前的运行循环
	if (num == 8) {
		// 停止当前的运行循环
		/*
		一旦停止了运行循环,后续代码能够执行,执行完毕后,线程被自动销毁
		*/
		CFRunLoopStop(CFRunLoopGetCurrent());
	}
}

3、API说明

@interface NSTimer : NSObject

/**
 * @brief 创建一个NSTimer对象,可以自定义执行方法及时间间隔,不会主动加入runloop中
 *
 * @param ti             时间间隔
 * @param invocation     执行方法的NSInvocation对象
 * @param yesOrNo        是否需要重复执行
 *
 * @return               返回创建的NSTimer对象
 *
 * @discussion           这个方法返回的定时器不会自动添加到Runloop中,需要手动添加到Runloop
 *                        举例:在某个视图的生命周期内需要定时执行某个处理方法,可以使用此方法创建一个定时器
 */
+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti invocation:(NSInvocation *)invocation repeats:(BOOL)yesOrNo;

/**
 * @brief 创建一个NSTimer对象,可以自定义执行方法及时间间隔,会自动加入runloop中
 *
 * @param ti             时间间隔
 * @param invocation     执行方法的NSInvocation对象
 * @param yesOrNo        是否需要重复执行
 *
 * @return               返回创建的NSTimer对象
 *
 * @discussion           这个方法创建的定时器会自动添加进当前的Runloop中进行调度
 *                        举例:在某个视图的生命周期内需要定时执行某个更新操作,可以使用此方法创建一个定时器
 */
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti invocation:(NSInvocation *)invocation repeats:(BOOL)yesOrNo;

/**
 * @brief 创建一个NSTimer对象,可以自定义目标及执行方法、时间间隔,不会主动加入runloop中
 *
 * @param ti             时间间隔
 * @param aTarget        执行方法的对象
 * @param aSelector      执行方法的方法名
 * @param userInfo       自定义的参数
 * @param yesOrNo        是否需要重复执行
 *
 * @return               返回创建的NSTimer对象
 *
 * @discussion           这个方法创建的定时器不会自动添加到当前的Runloop中,需要手动添加到Runloop
 *                        举例:在某个视图的生命周期内需要根据特定的时间间隔,定时刷新某个页面状态,可以使用此方法创建一个定时器
 */
+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(nullable id)userInfo repeats:(BOOL)yesOrNo;

/**
 * @brief 创建一个NSTimer对象,可以自定义目标及执行方法、时间间隔,会自动加入runloop中
 *
 * @param ti             时间间隔
 * @param aTarget        执行方法的对象
 * @param aSelector      执行方法的方法名
 * @param userInfo       自定义的参数
 * @param yesOrNo        是否需要重复执行
 *
 * @return               返回创建的NSTimer对象
 *
 * @discussion           这个方法创建的定时器会自动添加进当前的Runloop中进行调度
 *                        举例:在某个视图的生命周期内需要根据特定的时间间隔,自动进行更新操作,可以使用此方法创建一个定时器
 */
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(nullable id)userInfo repeats:(BOOL)yesOrNo;

/**
 * @brief 创建一个NSTimer对象,可以自定义时间间隔及执行代码块,不会主动加入runloop中
 *
 * @param interval       时间间隔
 * @param repeats        是否需要重复执行
 * @param block          执行代码块
 *
 * @return               返回创建的NSTimer对象
 *
 * @discussion           这个方法创建的定时器不会自动添加到当前的Runloop中,需要手动添加到Runloop
 *                        举例:在某个页面需要异步加载网络数据,并且每隔一段时间需要手动刷新数据,可以使用此方法创建一个定时器
 */
+ (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));

/**
 * @brief 创建一个NSTimer对象,可以自定义时间间隔及执行代码块,会自动加入runloop中
 *
 * @param interval       时间间隔
 * @param repeats        是否需要重复执行
 * @param block          执行代码块
 *
 * @return               返回创建的NSTimer对象
 *
 * @discussion           这个方法创建的定时器会自动添加进当前的Runloop中进行调度
 *                        举例:在某个页面需要进行自动更新操作,每隔一段时间自动执行某个方法,可以使用此方法创建一个定时器
 */
+ (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));

/**
 * @brief 创建一个NSTimer对象,可以自定义执行时间、时间间隔及执行代码块,不会主动加入runloop中
 *
 * @param date           初始执行时间
 * @param interval       时间间隔
 * @param repeats        是否需要重复执行
 * @param block          执行代码块
 *
 * @return               返回创建的NSTimer对象
 *
 * @discussion           这个方法创建的定时器不会自动添加到当前的Runloop中,需要手动添加到Runloop
 *                        举例:在某个视图的生命周期内需要定时执行某一操作,可以使用此方法创建一个定时器,如直播倒计时、游戏倒计时等
 */
- (instancetype)initWithFireDate:(NSDate *)date interval:(NSTimeInterval)interval repeats:(BOOL)repeats block:(void (^)(NSTimer *timer))block API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0));

/**
 * @brief 创建一个NSTimer对象,可以自定义执行时间、时间间隔及执行方法名,会自动加入runloop中
 *
 * @param date           初始执行时间
 * @param ti             时间间隔
 * @param t              执行方法的对象
 * @param s              执行方法的方法名
 * @param ui             自定义的参数
 * @param rep            是否需要重复执行
 *
 * @return               返回创建的NSTimer对象
 *
 * @discussion           这个方法创建的定时器会自动添加进当前的Runloop中进行调度
 *                        举例:多场景下需要执行一个相同的逻辑处理方法,不同的场景需要在不同的时间执行,可以使用此方法创建一个定时器,如各种定时任务、页面重复刷新等
 */
- (instancetype)initWithFireDate:(NSDate *)date interval:(NSTimeInterval)ti target:(id)t selector:(SEL)s userInfo:(nullable id)ui repeats:(BOOL)rep NS_DESIGNATED_INITIALIZER;

/**
 * @brief 立即执行一次定时器的方法
 *
 * @discussion           举例:在某次用户操作后需要立即执行某个方法时,可以手动调用此方法。
 */
- (void)fire;

/** 定时器开始执行时间 */
@property(copy) NSDate *fireDate;
/** 定时器循环执行的时间间隔 */
@property(readonly) NSTimeInterval timeInterval;
/** 系统允许的额外时间间隔,用于调整定时器执行时间误差(API_AVAILABLE) */
@property NSTimeInterval tolerance API_AVAILABLE(macos(10.9), ios(7.0), watchos(2.0), tvos(9.0));

/**
 * @brief 停止 NSTimer,防止再次触发计时器的事件
 *
 * 这个方法通常用于停止重复执行某个事件的计时器,可避免计时器被错误地执行多次。
 * 例如,你正在开发一个游戏中的计时器,希望每1秒钟更新一次分数。在游戏结束后,你需要调用此方法,停止计时器,以免计时器在此后持续更新分数。
 */
- (void)invalidate;

/** 定时器是否有效 */
@property(readonly, getter=isValid) BOOL valid;
/** 用户信息,可选类型 */
@property(nullable, readonly, retain) id userInfo;

@end
posted @ 2019-02-16 22:23  CH520  阅读(565)  评论(0编辑  收藏  举报