RunLoop

  • 与线程关系 :runloop依赖于线程,每一个线程都有一个与之对应的runloop,子线程的runloop需要手动启动,当线程结束,runloop也会结束
  • 运行
    [[NSRunLoop currentRunLoop]run];
    [loop1 runUntilDate:[NSDate date]];//[NSDate date]一直运行
    [loop2 runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:20]];
    // 运行一次runloop 直到 时间
    [[NSRunLoop currentRunLoop]acceptInputForMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:100]];
  • 停止
    1,上面有截止时间的到时间会停止运行
    2, // 停止当前线程循环
    CFRunLoopStop(CFRunLoopGetCurrent());
  • runloop添加
    1,端口源 runloop a和b交互
    // 创建端口
    NSPort *port = [[NSPort alloc]init];
    // 设置代理
    port.delegate = self;
    // 主线程添加接受消息端口 port
    [[NSRunLoop currentRunLoop]addPort:port forMode:NSRunLoopCommonModes];

    //开启子线程 传入端口 port
    [NSThread detachNewThreadSelector:@selector(aa:) toTarget:self withObject:port ];
    }
    /// port代理方法

  • (void)handlePortMessage:(NSPortMessage *)message{
    NSLog(@”%@”,message);
    }
    /// 子线程方法体
    -(void)aa:(id)sender{
    // 接受端口port
    NSPort *p = sender;
    // 通过接收的端口 向已经注册此端口的 runloop 发送消息
    [p sendBeforeDate:[NSDate dateWithTimeIntervalSinceNow:1] components:nil from:[NSPort port] reserved:0];

}
2,定时源 nstimer添加
3,cocoSelect源 perform。。。onThread 等事件

  • runloop观察者
    源是在合适的同步或异步事件发生时触发,而run loop观察者则是在run loop本身运行的特定时候触发。你可以使用run loop观察者来为处理某一特定事件或是进入休眠的线程做准备。你可以将run loop观察者和以下事件关联:

    1. Runloop入口

    2. Runloop何时处理一个定时器

    3. Runloop何时处理一个输入源

    4. Runloop何时进入睡眠状态

    5. Runloop何时被唤醒,但在唤醒之前要处理的事件

    6. Runloop终止

和定时器类似,在创建的时候你可以指定run loop观察者可以只用一次或循环使用。若只用一次,那么在它启动后,会把它自己从run loop里面移除,而循环的观察者则不会。定义观察者并把它添加到run loop,只能使用Core Fundation。下面的例子演示了如何创建run loop的观察者:

  • (void)addObserverToCurrentRunloop

{

// The application uses garbage collection, so noautorelease pool is needed.

NSRunLoop*myRunLoop = [NSRunLoop currentRunLoop];



// Create a run loop observer and attach it to the runloop.

CFRunLoopObserverContext  context = {0, self, NULL, NULL, NULL};

CFRunLoopObserverRef observer =CFRunLoopObserverCreate(kCFAllocatorDefault,

                                                          kCFRunLoopBeforeTimers, YES, 0, &myRunLoopObserver, &context);



if (observer)

{

    CFRunLoopRef    cfLoop = [myRunLoop getCFRunLoop];

   CFRunLoopAddObserver(cfLoop, observer, kCFRunLoopDefaultMode);

}

}

其中,kCFRunLoopBeforeTimers表示选择监听定时器触发前处理事件,后面的YES表示循环监听。

2.3 RunLoop的事件队列

每次运行run loop,你线程的run loop对会自动处理之前未处理的消息,并通知相关的观察者。具体的顺序如下:

1. 通知观察者run loop已经启动
2. 通知观察者任何即将要开始的定时器
3. 通知观察者任何即将启动的非基于端口的源
4. 启动任何准备好的非基于端口的源
5. 如果基于端口的源准备好并处于等待状态,立即启动;并进入步骤9。
6. 通知观察者线程进入休眠
7. 将线程置于休眠直到任一下面的事件发生:
    * 某一事件到达基于端口的源
    * 定时器启动
    * Run loop设置的时间已经超时
    * run loop被显式唤醒
8. 通知观察者线程将被唤醒。
9. 处理未处理的事件
    * 如果用户定义的定时器启动,处理定时器事件并重启run loop。进入步骤2
    * 如果输入源启动,传递相应的消息
    * 如果run loop被显式唤醒而且时间还没超时,重启run loop。进入步骤2
10. 通知观察者run loop结束。

*
因为定时器和输入源的观察者是在相应的事件发生之前传递消息,所以通知的时间和实际事件发生的时间之间可能存在误差。如果需要精确时间控制,你可以使用休眠和唤醒通知来帮助你校对实际发生事件的时间。

因为当你运行run loop时定时器和其它周期性事件经常需要被传递,撤销run loop也会终止消息传递。典型的例子就是鼠标路径追踪。因为你的代码直接获取到消息而不是经由程序传递,因此活跃的定时器不会开始直到鼠标追踪结束并将控制权交给程序。

Run loop可以由run loop对象显式唤醒。其它消息也可以唤醒run loop。例如,添加新的非基于端口的源会唤醒run loop从而可以立即处理输入源而不需要等待其他事件发生后再处理。

从这个事件队列中可以看出:

①如果是事件到达,消息会被传递给相应的处理程序来处理, runloop处理完当次事件后,run loop会退出,而不管之前预定的时间到了没有。你可以重新启动run loop来等待下一事件。

②如果线程中有需要处理的源,但是响应的事件没有到来的时候,线程就会休眠等待相应事件的发生。这就是为什么run loop可以做到让线程有工作的时候忙于工作,而没工作的时候处于休眠状态。

2.4什么时候使用run loop

仅当在为你的程序创建辅助线程的时候,你才需要显式运行一个run loop。Run loop是程序主线程基础设施的关键部分。所以,Cocoa和Carbon程序提供了代码运行主程序的循环并自动启动run loop。IOS程序中UIApplication的run方法(或Mac OS X中的NSApplication)作为程序启动步骤的一部分,它在程序正常启动的时候就会启动程序的主循环。类似的,RunApplicationEventLoop函数为Carbon程序启动主循环。如果你使用xcode提供的模板创建你的程序,那你永远不需要自己去显式的调用这些例程。

对于辅助线程,你需要判断一个run loop是否是必须的。如果是必须的,那么你要自己配置并启动它。你不需要在任何情况下都去启动一个线程的run loop。比如,你使用线程来处理一个预先定义的长时间运行的任务时,你应该避免启动run loop。Run loop在你要和线程有更多的交互时才需要,比如以下情况:

1. 使用端口或自定义输入源来和其他线程通信
2. 使用线程的定时器
3. Cocoa中使用任何performSelector…的方法
4. 使线程周期性工作

*
如果你决定在程序中使用run loop,那么它的配置和启动都很简单。和所有线程编程一样,你需要计划好在辅助线程退出线程的情形。让线程自然退出往往比强制关闭它更好。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值