iOS-NSRunLoop编程详解



-------------------------iOS-NSRunLoop编程详解1---------------------------------
编程

一.简介

NSRunloop在编程中扮演的是一个管理者角色,它管理的对象是输入源,NSRunloop处理的对象包括鼠标和键盘的系统事件,此外还有NSPort,NSTimer,NSConnection类的对象。在应用程序中你不能显示的调用NSRunloop来建立NSRunloop实例对象,每个线程和主线程中都会默认的有一个NSRunloop的实例变量。若是你想获得每一个线程的NSRunloop对象实例变量,能够经过它的类方法调用获得[NSRunloop currentRunLoop];它是不安全的类型因此多线程编程时要当心。

    
    NSLog(@"我是主线程的NSRunloop%@",[NSRunLoop currentRunLoop]);
    [NSThread detachNewThreadSelector:@selector(newThread:) toTarget:self withObject:nil];
    
}

-(void)newThread:(id)sender{
    [[NSRunLoop currentRunLoop] run];
    NSLog(@"我是子线程的NSRunloop%@",[NSRunLoop currentRunLoop]);
}

分别获得主线程和子线程中NSRunLoop对象,打印以后里面包含了它的一些属性信息和时间信息等有兴趣能够本身打印出来看,能够在任什么时候候经过[NSRunloop mainRunLoop]获得主线程的NSRunLoop对象。

2015-01-11 14:45:58.839 GCDTest[716:31530]我是主线程的NSRunloop<CFRunLoop 0x7fd399d07280 [0x1074c89a0]>。。。。。。。安全

2015-01-11 14:45:58.861 GCDTest[716:31584]我是子线程的NSRunloop<CFRunLoop 0x7fd399e2e2a0 [0x1074c89a0]>。。。。。。。多线程


函数介绍:函数

//添加一个定时器,当定时器的时间到时就会触发定时器制定的函数oop

- (void)addTimer:(NSTimer *)timer forMode:(NSString *)mode;spa

//添加一个NSPort,当NSPort对象有消息就会触发NSPort的代理方法
线程

- (void)addPort:(NSPort *)aPort forMode:(NSString *)mode;代理

//移除端口code

- (void)removePort:(NSPort *)aPort forMode:(NSString *)mode;component

//子线程的NSRunLoop是没有启动的,因此要经过该函数来启动NSRunLoop

- (void)run;



二.时间源


1.在主线程中不用调用run函数,只有把timer加入到NSRunloop中才会触发timerFire函数,间隔时间为3秒
- (void)viewDidLoad {
    [super viewDidLoad];
    
    NSTimer *timer = [[NSTimer alloc]initWithFireDate:[NSDate date] interval:3 target:self selector:@selector(timerFire:) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
    
    
}

-(void)timerFire:(id)sender{
    NSLog(@"i am fired");
}
运行结果:相差三秒左右

2015-01-11 15:10:06.770 GCDTest[812:39356] i am fired

2015-01-11 15:10:09.758 GCDTest[812:39356] i am fired

2015-01-11 15:10:12.758 GCDTest[812:39356] i am fired

2015-01-11 15:10:15.759 GCDTest[812:39356] i am fired

2015-01-11 15:10:18.759 GCDTest[812:39356] i am fired

2015-01-11 15:10:21.759 GCDTest[812:39356] i am fired

2015-01-11 15:10:24.758 GCDTest[812:39356] i am fired


2.在子线程中加入时间数据源

要手动的调用run函数不然没有任何输出
- (void)viewDidLoad {
    [super viewDidLoad];
    
   
    
    [NSThread detachNewThreadSelector:@selector(newThread:) toTarget:self withObject:nil];
    
}

-(void)newThread:(id)sender{
    NSTimer *timer = [[NSTimer alloc]initWithFireDate:[NSDate date] interval:3 target:self selector:@selector(timerFire:) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
    [[NSRunLoop currentRunLoop] run];
}

-(void)timerFire:(id)sender{
    NSLog(@"i am fired");
}


运行结果:输出相差3秒

2015-01-11 15:12:53.509 GCDTest[854:40639] i am fired

2015-01-11 15:12:56.514 GCDTest[854:40639] i am fired

2015-01-11 15:12:59.514 GCDTest[854:40639] i am fired

2015-01-11 15:13:02.514 GCDTest[854:40639] i am fired

2015-01-11 15:13:05.513 GCDTest[854:40639] i am fired

2015-01-11 15:13:08.514 GCDTest[854:40639] i am fired

2015-01-11 15:13:11.514 GCDTest[854:40639] i am fired


三.端口数据源

- (void)viewDidLoad {
    
    [super viewDidLoad];
    
    NSMachPort *  port = [[NSMachPort alloc]init];    //#1
    [port setDelegate:self];                          //#2
    [[NSRunLoop currentRunLoop] addPort:port forMode:NSRunLoopCommonModes];//#3
    [NSThread detachNewThreadSelector:@selector(newThread:) toTarget:self withObject:port]; //#4
    
}

- (void)handleMachMessage:(void *)msg{   //#5
    NSLog(@"hello wrod%s",msg);          //#6
}

-(void)newThread:(NSMachPort *)sender{
    NSMachPort *p = [[NSMachPort alloc]init];   //#7
    [sender sendBeforeDate:[NSDate distantFuture] components:nil from:p reserved:0];//#8
    NSLog(@"subthread=%@",[NSThread currentThread]);
}


运行结果:

2015-01-14 22:19:12.519 GCDTest[742:27354] subthread=<NSThread: 0x7ff700f21ed0>{number = 2, name = (null)}

2015-01-14 22:19:12.599 GCDTest[742:27249] hello wrod


代码说明:

#1:新建一个port,至关于一个线程的耳朵,这时耳朵并无安装上,

#2:给它设置一个代理,当这个耳朵听到声音时,代理要对msg作出相应。

#3:把port加入到当前线程的runloop上,至关于给这个线程的装上了耳朵

#4:新建一个线程,并告诉这个线程若是你要向当前线程说话,你能够经过port传递消息

#6:当主线程的耳朵port获得消息时,作相应的处理

#7-#8:你也能够给该线程装上一个port耳朵并安装,你能够经过sender 传给主线程信息




图解:




小结:注意mianRunloop会自动的run,子线程要手动run,加入到runloop的源要选定代理回调,输入源的类型。(1.runloop类型,2.回调的选择,3,输入源的类型)
相关文章
相关标签/搜索