[iOS学习笔记]runloop runMode方法调研

 
//
//  ViewController.m
//  ThreadTest
//
//  Created by skyko on 16/5/31.
//  Copyright © 2016年 helios. All rights reserved.
//

#import "ViewController.h"

@interface ViewController ()

@property (nonatomic, strong) NSThread *thread;

@property (nonatomic, assign) BOOL isAlive;

@property (nonatomic, strong) NSTimer *timer;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    NSLog(@"viewDidLoad");
    self.isAlive = YES;
    
    self.thread = [[NSThread alloc] initWithTarget:self
                                          selector:@selector(workThread:)
                                            object:nil];
    [self.thread setName:@"MyCustomThread"];
    [self.thread start];

    //延迟3s后向线程添加任务
    dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 3 * NSEC_PER_SEC);
    dispatch_after(time, dispatch_get_main_queue(), ^{
        [self performSelector:@selector(handleSomeThing)
                     onThread:self.thread
                   withObject:nil
                waitUntilDone:NO];
    });
}


- (void)workThread:(id)data {
    NSLog(@"workThread");
    NSRunLoop *runloop = [NSRunLoop currentRunLoop];
    [runloop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];//不添加这一行的话,在有任务添加前下面的while循环会一直执行,原因见后面解释
    
    while (_isAlive) { //isAlive用于控制该线程的运行周期,当设置isAlive为NO时,该线程执行完当前任务后退出并销毁
        NSLog(@"--->");
        //在设置的时间内执行NSDefaultRunLoopMode模式的任务
        //如果队列中暂时没有任务会一直堵塞直至有任务进入队列
        //任务执行完成后接着循环
        //超时会进入下一次循环
        [runloop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
        NSLog(@"<---");
    }
}

- (void)handleSomeThing {
    NSLog(@"handleSomeThing before sleep");
    [NSThread sleepForTimeInterval:1.0f];
    NSLog(@"handleSomeThing after sleep");
}

@end

 

运行结果打印:

2016-05-31 11:42:25.020 ThreadTest[1940:76011] viewDidLoad
2016-05-31 11:42:25.020 ThreadTest[1940:76221] workThread
2016-05-31 11:42:25.021 ThreadTest[1940:76221] --->
2016-05-31 11:42:28.311 ThreadTest[1940:76221] handleSomeThing before sleep
2016-05-31 11:42:29.315 ThreadTest[1940:76221] handleSomeThing after sleep
2016-05-31 11:42:29.315 ThreadTest[1940:76221] <---
2016-05-31 11:42:29.315 ThreadTest[1940:76221] --->

 

原文文档介绍:

Runs the loop once, blocking for input in the specified mode until a given date.

//执行loop一次,堵塞等待给定模式的输入直至给定的时间点

Parameters

mode

The mode in which to run. You may specify custom modes or use one of the modes listed in Run Loop Modes.

limitDate

The date until which to block.

Return Value

YES if the run loop ran and processed an input source or if the specified timeout value was reached; otherwise, NO if the run loop could not be started.

//当runloop正在运行并处理了一个输入源或者超时返回YES,否则如果runloop并未启动就返回NO

 

Discussion

If no input sources or timers are attached to the run loop, this method exits immediately and returns NO; otherwise, it returns after either the first input source is processed or limitDate is reached. Manually removing all known input sources and timers from the run loop does not guarantee that the run loop will exit immediately. OS X may install and remove additional input sources as needed to process requests targeted at the receiver’s thread. Those sources could therefore prevent the run loop from exiting.

 如果没有一个输入源或者timer添加到runloop中,该方法会立刻退出并返回NO(这就是上面demo中添加下面代码的原因),否则该方法会在执行完队列中第一个输入源或超时后返回,手动移除runloop中所有输入源和timer并不能保证runloop立刻退出.OS X系统可能在线程中添加或移除一些额外的输入源来处理必须的任务,因此这些输入源可能会阻止runloop的退出.

[runloop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];


NOTE

A timer is not considered an input source and may fire multiple times while waiting for this method to return

timer不是一个输入源并且可能在等待该方法返回过程中会多次启动

 

总结:

[runloop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
1.在设置的时间内执行设置的模式的任务
2.如果队列中暂时没有任务会一直堵塞直至有任务进入队列
3.任务执行完成后该方法退出
4.超时后该方法退出
 
posted @ 2016-05-31 12:16  skyko  阅读(550)  评论(0编辑  收藏  举报