-
(
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,加深理解NSTimer和NSRunLoop的关系。

曾经博文中提到延迟调用的方法,事实上就是在当前线程的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;

将NSTimer加入至RunLoop中的两种方法差别的更多相关文章

  1. javascript原型继承中的两种方法对比

    在实际的项目中,我们通常都是用构造函数来创建一个对象,再将一些常用的方法添加到其原型对象上.最后要么直接实例化该对象,要么将它作为父类,再申明一个对象,继承该父类. 而在继承的时候有两种常用方式,今天 ...

  2. C#把某个数组的一部分复制到另一个数组中的两种方法:Buffer.BlockCopy和Array.Copy

    static void Main(string[] args) { , , , , , }; ;//目标数组大小 int int_size = sizeof(int);//用于获取值类型的字节大小. ...

  3. Js类的静态方法与实例方法区分以及jQuery如何拓展两种方法

    上学时C#老师讲到对象有两类方法,静态方法(Static)和实例方法(非Static),当时不理解静态是为何意,只是强记. 后来从事前端工作,一直在对类(即对象,Js中严格来说没有类的定义,虽众所周知 ...

  4. .net中创建xml文件的两种方法

    .net中创建xml文件的两种方法 方法1:根据xml结构一步一步构建xml文档,保存文件(动态方式) 方法2:直接加载xml结构,保存文件(固定方式) 方法1:动态创建xml文档 根据传递的值,构建 ...

  5. Redis中持久化的两种方法详解

    Redis提供了两种不同的持久化方法来将数据存储到硬盘里面.一种方法叫快照(snapshotting),它可以将存在于某一时刻的所有数据都写入硬盘里;另一种方法教只追加文件(append-only f ...

  6. 【转】oracle 中随机取一条记录的两种方法

    oracle 中随机取一条记录的两种方法 V_COUNT INT:=0; V_NUM INT :=0; 1:TBL_MYTABLE 表中要有一个值连续且唯一的列FID BEGIN SELECT COU ...

  7. MySQL中的两种临时表

    MySQL中的两种临时表 伯乐在线2016-07-06 05:16:52阅读(4556)评论(3) 声明:本文由入驻搜狐公众平台的作者撰写,除搜狐官方账号外,观点仅代表作者本人,不代表搜狐立场.举报 ...

  8. 在shell script中进行数值运算的两种方法

    方法1:使用"$((计算式))"的方式进行数值运算,不需要使用declare命令显示声明数值型变量来存储计算结果: 方法2:使用declare命令配合"-i"选 ...

  9. ORACLE 查询一个数据表后通过遍历再插入另一个表中的两种写法

    ORACLE 查询一个数据表后通过遍历再插入另一个表中的两种写法 语法 第一种: 通过使用Oracle语句块  --指定文档所有部门都能查看 declare cursor TABLE_DEPT and ...

随机推荐

  1. django 在非空的字段里插入现象表述

    1.char 类型设置为非空 对于字段不赋值 默认储存为''(空字符串) 2.int 类型设置为非空 对于字段不赋值 单条插入 报错        多条数据同时插入 默认设置为0

  2. laravel中soapServer支持wsdl的例子

    最近在对接客户的CRM系统,获取令牌时,要用DES方式加密解密,由于之前没有搞错这种加密方式,经过请教了"百度"和"谷歌"两个老师后,结合了多篇文档内容后,终于 ...

  3. vuex 闲置状态重置方案

    前言 大型单页应用(后面都是指spa),我们往往会通过使用状态管理器 vuex 去解决组件间状态共享与状态传递等问题.这种应用少则几十个单页,多则上百个单页.随着路由的频繁切换,每个路由对应的 vue ...

  4. MySQL日志设置及查看方法

    MySQL有以下几种日志: 错误日志: -log-err 查询日志: -log 慢查询日志: -log-slow-queries 更新日志: -log-update 二进制日志: -log-bin 默 ...

  5. 用motion实现家庭视频监控

    需求?当然不是为了艳照.你们这些猥琐的人类! 毕竟家里总会有没人的时候,出门走到半路忘记煤气灶是不是关了,还得回去看看. 在这个科技以人为本的时代,当然应该是拿出智能手机联网看看啦.还有万一有人闯空门 ...

  6. php如何截取出视频中的指定帧作为图片

    php如何截取出视频中的指定帧作为图片 一.总结 一句话总结:截取视频指定帧为图片,php ffmpeg扩展已经完美实现,并且php ffmpeg是开源的 二.php如何截取出视频中的指定帧作为图片 ...

  7. 剑指offer—java版本实现

    终于完成了全部!所有的心累这时候都觉得很值得啊!爽! https://github.com/xurui1995/Sword-pointing-to-offer

  8. centos 7.3 配置vnc 服务 图形界面登录

    1.检查系统是否有安装tigervnc-server软件包 rpm -qa |grep vnc 默认的系统未装tigervnc-server软件包 2.安装tigervnc-server软件包 yum ...

  9. 【基础篇】activity生命周期及数据保存

    常见的Android 的界面,均采用Activity+view的形式显示的,一提到Activity,立即就能联想到Activity的生命周期与状态的保存. 下面先从Activity的生命周期开始说起  ...

  10. gym 100735I

    Description standard input/outputStatements You are given three numbers. Is there a way to replace v ...