RunLoop

作者: 薛定谔的熊 | 来源:发表于2016-09-18 01:22 被阅读0次

    参考:http://www.cocoachina.com/ios/20150601/11970.html

    Paste_Image.png Paste_Image.png

    1、Timer

    - (void)timer2
    {
        // 调用了scheduledTimer返回的定时器,已经自动被添加到当前runLoop中,而且是NSDefaultRunLoopMode
        NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(run) userInfo:nil repeats:YES];
        
        // 修改模式
        [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
    }
    
    - (void)timer
    {
        NSTimer *timer = [NSTimer timerWithTimeInterval:2.0 target:self selector:@selector(run) userInfo:nil repeats:YES];
        // 定时器只运行在NSDefaultRunLoopMode下,一旦RunLoop进入其他模式,这个定时器就不会工作
        //    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
        
        // 定时器只运行在UITrackingRunLoopMode下,一旦RunLoop进入其他模式,这个定时器就不会工作
        //    [[NSRunLoop currentRunLoop] addTimer:timer forMode:UITrackingRunLoopMode];
        
        // 定时器会跑在标记为common modes的模式下
        // 标记为common modes的模式:UITrackingRunLoopMode和NSDefaultRunLoopMode
        [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
    }
    
    - (void)run
    {
        NSLog(@"----run");
    }
    

    2、Observer

    - (void)observer
    {
        // 创建observer
        CFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler(CFAllocatorGetDefault(), kCFRunLoopAllActivities, YES, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {
            NSLog(@"----监听到RunLoop状态发生改变---%zd", activity);
        });
    //    /* Run Loop 状态监听 */
    //    typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) {
    //        kCFRunLoopEntry = (1UL << 0),    //即将进入Loop
    //        kCFRunLoopBeforeTimers = (1UL << 1),//即将处理Timer
    //        kCFRunLoopBeforeSources = (1UL << 2),//即将处理Source
    //        kCFRunLoopBeforeWaiting = (1UL << 5),//即将进入休眠
    //        kCFRunLoopAfterWaiting = (1UL << 6),//刚从休眠中唤醒
    //        kCFRunLoopExit = (1UL << 7),//即将退出Loop
    //        kCFRunLoopAllActivities = 0x0FFFFFFFU
    //    };
        // 添加观察者:监听RunLoop的状态
        CFRunLoopAddObserver(CFRunLoopGetCurrent(), observer, kCFRunLoopDefaultMode);
        
        // 释放Observer
    /*
        CF的内存管理(Core Foundation)
        1.凡是带有Create、Copy、Retain等字眼的函数,创建出来的对象,都需要在最后做一次release
        * 比如CFRunLoopObserverCreate
        2.release函数:CFRelease(对象);
     */
        CFRelease(observer);
    }
    

    3、应用场景:

    • 保住线程的生命(用属性强引用的方式不好使)
    
    #import "ViewController.h"
    #import "XMGThread.h"
    
    @interface ViewController ()
    
    /** 线程对象 */
    @property (nonatomic, strong) XMGThread *thread;
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        self.thread = [[XMGThread alloc] initWithTarget:self selector:@selector(execute) object:nil];
        [self.thread start];
    }
    
    - (void)execute
    {
        NSLog(@"----------execute----%@", [NSThread currentThread]);
        //在当前模式添加端口(因为如果当前模式没有东西,RunLoop开启会马上退出)
        [[NSRunLoop currentRunLoop] addPort:[NSPort port] forMode:NSDefaultRunLoopMode];
        // 启动(run执行首先会判断当前模式有没有东西,如果没有就会退出)
        [[NSRunLoop currentRunLoop] run];
        //移除
    //    - (void)removePort:(NSPort *)aPort forMode:(NSRunLoopMode)mode;
        
        NSLog(@"---------");
        
        // 类似于上面的[[NSRunLoop currentRunLoop] run]
        //    [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
        //    [[NSRunLoop currentRunLoop] runUntilDate:[NSDate distantFuture]];
    }
    
    - (void)test
    {
        NSLog(@"----------test----%@", [NSThread currentThread]);
    }
    
    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
    {
    //这句方法实质是给self.thread这条线程中的RunLoop添加了Source(有source之后,RunLoop就不会退出了)
        [self performSelector:@selector(test) onThread:self.thread withObject:nil waitUntilDone:NO];
    }
    
    • 在特定模式下执行操作
    - (void)useImageView
    {
        // 只在NSDefaultRunLoopMode模式下显示图片
        [self.imageView performSelector:@selector(setImage:) withObject:[UIImage imageNamed:@"placeholder"] afterDelay:3.0 inModes:@[NSDefaultRunLoopMode]];
    }
    
    • 子线程添加timer

    需将timer手动添加到当前线程的RunLoop并开启,不然不会执行test方法。主线程下默认做了这些操作。

    
    #import "ViewController.h"
    #import "XMGThread.h"
    
    @interface ViewController ()
    
    /** 线程对象 */
    @property (nonatomic, strong) XMGThread *thread;
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        self.thread = [[XMGThread alloc] initWithTarget:self selector:@selector(execute) object:nil];
        [self.thread start];
    }
    
    //-(void)execute
    //{
    //   NSTimer *timer = [NSTimer timerWithTimeInterval:2.0 target:self selector:@selector(test) userInfo:nil repeats:YES];
    //添加time到模式
    //    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
    //    [[NSRunLoop currentRunLoop] run];
    //}
    
    - (void)execute
    {
    //scheduledTimerWithTimeInterval创建的time默认会添加到RunLoop默认模式
        [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(test) userInfo:nil repeats:YES];
        
        [[NSRunLoop currentRunLoop] run];
    }
    

    4、RunLoop自动释放池什么时候释放?

    在RunLoop睡眠之前释放(KCFRunLoopBeforeWaiting)

    相关文章

      网友评论

          本文标题:RunLoop

          本文链接:https://www.haomeiwen.com/subject/iaswettx.html