• NSRunLoop概述和原理


    Iphone开发-NSRunLoop概述和原理
    1.什么是NSRunLoop?
    我们会经常看到这样的代码:


    - (IBAction)start:(id)sender
    {
    pageStillLoading = YES;
    [NSThread detachNewThreadSelector:@selector(loadPageInBackground:)toTarget:self withObject:nil];
    [progress setHidden:NO];
    while (pageStillLoading) {
    [NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
    }
    [progress setHidden:YES];
    }

      这段代码很神奇的,因为他会“暂停”代码运行,而且程序运行不会因为这里有一个while循环而受到影响。在[progress setHidden:NO]执行之后,整个函数像暂停了一样,停在循环里面,等loadPageInBackground里面的操作都完成了以后,
    才让[progress setHidden:YES]运行。这样做就显得简单,而且逻辑很清晰。如果不这样做,就需要在loadPageInBackground里面表示load完成的地方调用[progress setHidden:YES],显得代码不紧凑而且容易出错。
    那么具体什么是NSRunLoop呢?其实NSRunLoop的本质是一个消息机制的处理模式。如果你对vc++编程有一定了解,在windows中,有一系列很重要的函数SendMessage,PostMessage,GetMessage,
    这些都是有关消息传递处理的API。但是在你进入到Cocoa的编程世界里面,我不知道你是不是走的太快太匆忙而忽视了这个很重要的问题,Cocoa里面就没有提及到任何关于消息处理的API,
    开发者从来也没有自己去关心过消息的传递过程,好像一切都是那么自然,像大自然一样自然?在Cocoa里面你再也不用去自己定义WM_COMMAD_XXX这样的宏来标识某个消息,
    也不用在switch-case里面去对特定的消息做特别的处理。难道是Cocoa里面就没有了消息机制?答案是否定的,只是Apple在设计消息处理的时候采用了一个更加高明的模式,那就是RunLoop。

     

     

    利用NSRunLoop阻塞NSOperation线程
    使用NSOperationQueue简化多线程开发中介绍了多线程的开发,我这里主要介绍一下使用NSRunLoop阻塞线程。
    主要使用在NStimer定时启用的任务或者异步获取数据的情况如socket获取网络数据,要阻塞线程,直到获取数据之后在释放线程。
    下面是线程中没有使用NSRunLoop阻塞线程的代码和执行效果:
    线程类:

    #import <Foundation/Foundation.h> 
    @interface MyTask : NSOperation {     

    @end
    #import "MyTask.h" 
    @implementation MyTask 
    -(void)main     
    {      
        NSLog(@"开始线程=%@",self);      
        [NSTimer timerWithTimeInterval:2 target:self selector:@selector(hiandeTime:) userInfo:nil repeats:NO];      
    }      
    -(void)hiandeTime:(id)sender      
    {      
        NSLog(@"执行了NSTimer");      
    }      
    -(void)dealloc      
    {      
        NSLog(@"delloc mytask=%@",self);      
        [super dealloc];      

    @end

    线程添加到队列中:

    - (void)viewDidLoad     
    {      
        [super viewDidLoad];      
        NSOperationQueue *queue=[[NSOperationQueue alloc] init];      
        MyTask *myTask=[[[MyTask alloc] init] autorelease];      
        [queue addOperation:myTask];      
        MyTask *myTask1=[[[MyTask alloc] init] autorelease];      
        [queue addOperation:myTask1];      
        MyTask *myTask2=[[[MyTask alloc] init] autorelease];      
        [queue addOperation:myTask2];      
        [queue release];      
    }

    执行结果是:
    2011-07-25 09:44:45.393 OperationDemo[20676:1803] 开始线程=<MyTask: 0x4b4dea0>   
    2011-07-25 09:44:45.393 OperationDemo[20676:5d03] 开始线程=<MyTask: 0x4b50db0>    
    2011-07-25 09:44:45.396 OperationDemo[20676:1803] 开始线程=<MyTask: 0x4b51070>    
    2011-07-25 09:44:45.404 OperationDemo[20676:6303] delloc mytask=<MyTask: 0x4b4dea0>    
    2011-07-25 09:44:45.404 OperationDemo[20676:5d03] delloc mytask=<MyTask: 0x4b50db0>    
    2011-07-25 09:44:45.405 OperationDemo[20676:6303] delloc mytask=<MyTask: 0x4b51070>

    可以看到,根本没有执行NSTimer中的方法,线程就释放掉了,我们要执行
    NSTimer中的方法,就要利用NSRunLoop阻塞线程。下面是修改后的代码:

    -(void)main     
    {      
        NSLog(@"开始线程=%@",self);      
        NSTimer *timer=[NSTimer timerWithTimeInterval:2 target:self selector:@selector(hiandeTime) userInfo:nil repeats:NO];      
        [timer fire];      
        while (!didDisconnect) {      
            [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];      
        }      
    }
    执行结果如下:
    2011-07-25 10:07:00.543 OperationDemo[21270:1803] 开始线程=<MyTask: 0x4d16380>     
    2011-07-25 10:07:00.543 OperationDemo[21270:5d03] 开始线程=<MyTask: 0x4d17790>      
    2011-07-25 10:07:00.550 OperationDemo[21270:6303] 开始线程=<MyTask: 0x4d17a50>      
    2011-07-25 10:07:00.550 OperationDemo[21270:1803] 执行了NSTimer      
    2011-07-25 10:07:00.551 OperationDemo[21270:5d03] 执行了NSTimer      
    2011-07-25 10:07:00.552 OperationDemo[21270:6303] 执行了NSTimer      
    2011-07-25 10:07:00.556 OperationDemo[21270:6503] delloc mytask=<MyTask: 0x4d16380>      
    2011-07-25 10:07:00.557 OperationDemo[21270:6303] delloc mytask=<MyTask: 0x4d17790>      
    2011-07-25 10:07:00.557 OperationDemo[21270:5d03] delloc mytask=<MyTask: 0x4d17a50>
    我们可以使用NSRunLoop进行线程阻塞。
  • 相关阅读:
    [PCB设计] 1、硬件原理图设计规范(一)——基本原则
    [每日电路图] 8、三轴加速度计LIS3DH电路图及功耗等指标
    [安卓] 19、一个蓝牙4.0安卓DEMO
    [异常解决] MPU6050启动异常读出陀螺仪和加速度计的值全为0的解决办法
    [异常解决] android studio检测不到手机的解决办法——ADB驱动自己安装
    [每日电路图] 7、设计一个PCB的流程及细节·总结——给外行的同学或刚入行的同学一个宏观鸟瞰电路板设计的大致流程的文章
    [专业名词·硬件] 2、DCDC、LDO电源稳压基本常识(包含基本原理、高效率模块设计、常见问题、基于nRF51822电源管理模块分析等)·长文
    mysql获取某个字段平均值方法AVG函数的使用
    Linux设置SSH隧道连接
    docker入门实例(转载)
  • 原文地址:https://www.cnblogs.com/linyawen/p/2594982.html
Copyright © 2020-2023  润新知