将NSTimer加入至RunLoop中的两种方法差别
-
(
BOOL
)application:(UIApplication
*)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window
= [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
//用NSObject的方法创建一个多线程
[self
performSelectorInBackground:@selector(multiThread) withObject:nil];
self.window.backgroundColor
= [UIColor whiteColor];
[self.window
makeKeyAndVisible];
return
YES;
}
-
(
void
)multiThread
{
NSAutoreleasePool
*pool = [[NSAutoreleasePool alloc] init];
if
(![NSThread isMainThread]) {
//
第1种方式
//此种方式创建的timer已经加入至runloop中
//
[NSTimer scheduledTimerWithTimeInterval:1.0f target:self selector:@selector(timerAction) userInfo:nil repeats:YES];
//保持线程为活动状态,才干保证定时器运行
//
[[NSRunLoop currentRunLoop] run];//已经将nstimer加入到NSRunloop中了
//第2种方式
//此种方式创建的timer没有加入至runloop中
NSTimer
*timer = [NSTimer timerWithTimeInterval:1.0f target:self selector:@selector(timerAction) userInfo:nil repeats:YES];
//将定时器加入到runloop中
[[NSRunLoop
currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
[[NSRunLoop
currentRunLoop] run];
NSLog(@
"多线程结束"
);
}
[pool
release];
}
-
(
void
)timerAction
{
//定时器也是在子线程中运行的
if
(![NSThread isMainThread]) {
NSLog(@
"定时器"
);
}
}
理解run loop后,才干彻底理解NSTimer的实现原理,也就是说NSTimer实际上依赖run loop实现的。
先看看NSTimer的两个经常用法:
+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget
selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)yesOrNo; //生成timer但不运行
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget
selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)yesOrNo; //生成timer而且纳入当前线程的run loop来运行
NSRunLoop与timer有关方法为:
- (void)addTimer:(NSTimer *)timer forMode:(NSString *)mode; //在run
loop上注冊timer
主线程已经有run loop,所以NSTimer一般在主线程上执行都不必再调用addTimer:。但在非主线程上执行必须配置run loop。该线程的main方法演示样例代码例如以下:
- (void)main
{
NSTimer *myTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timer:) userInfo:nil repeats:YES];
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
[runLoop addTimer:myTimer forMode:NSDefaultRunLoopMode]; //实际上这步是不须要,scheduledTimerWithTimeInterval已经纳入当前线程执行。
假设使用timerWithTimeInterval则须要
while (condition)
[runLoop run];
}
实际上这个线程无法退出,由于有timer事件须要处理。[runLoop run]会一直无法返回。
解决的方法就是设置一个截止时间:
[runLoop runUntilDate:[NSDate dateWithTimeIntervalSinceNow:10.0]]; //每隔10秒检查下线程循环条件,当然时间值能够依据实际情况来定。
我们通常在主线程中使用NSTimer。有个实际遇到的问题须要注意。当滑动界面时,系统为了更好地处理UI事件和滚动显示,主线程runloop会临时停止处理一些其他事件,这时主线程中执行的NSTimer就会被暂停。解决的方法就是改变NSTimer执行的mode(mode能够看成事件类型)。不使用缺省的NSDefaultRunLoopMode,而是改用NSRunLoopCommonModes,这样主线程就会继续处理NSTimer事件了。详细代码例如以下:
NSTimer *timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(timer:) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
大家能够參看博文 p=209" style="color:rgb(29,88,209); text-decoration:none">http://bluevt.org/? p=209
曾经博文中提到延迟调用的方法,事实上就是在当前线程的run loop上注冊timer来实现定时执行的。所以假设是在非主线程上使用,一定要有一个run loop。
- (void)performSelector:(SEL)aSelector withObject:(id)anArgument
afterDelay:(NSTimeInterval)delay inModes:(NSArray*)modes;
- (void)performSelector:(SEL)aSelector withObject:(id)anArgument
afterDelay:(NSTimeInterval)delay;
最新文章
- 一眼看懂深浅拷贝(clone)-C#
- Delete Volume 操作 - 每天5分钟玩转 OpenStack(57)
- Mysql完全手册(笔记一,底层与内置函数)
- [Android Studio] *.jar 与 *.aar 的生成与*.aar导入项目方法
- js实现继承的两种方式
- iOS学习—JSON数据解析
- iOS多线程的初步研究(七)-- dispatch对象
- JProfiler 使用说明
- yii2怎样写规则可以隐藏url地址里的控制器名字
- Java API ——Collection集合类 &; Iterator接口
- 【无聊放个模板系列】BZOJ 3172 (AC自动机)
- Alias Method解决随机类型概率问题
- cf D. Valera and Fools
- 团队介绍 | 魅动 Magic Motion
- 【CSA72G】【XSY3316】rectangle 线段树 最小生成树
- 关于PJ 10.27
- jQuery获取URL中的参数
- python安装模块方法汇总
- kafka系列七、kafka核心配置
- 085 HBase的二级索引,以及phoenix的安装(需再做一次)
热门文章
- Unity 如何将apk放到Android系统的system里
- 15 hbase 学习(十五)缓存机制以及可以利用SSD作为存储的BucketCache
- Objective-C中的同步线程的锁
- MapReduce实现线性回归
- 剑指Offer面试题27(Java版):二叉搜索树与双向链表
- 烦人的Facebook分享授权
- UVALive - 6266 Admiral 费用流
- Ionic2集成ArcGIS JavaScript API.md
- [ Linux ] 釋放記憶體指令(cache) - 轉載
- React开发实时聊天招聘工具 -第六章 登陆注册(1)