iOS NSRunLoop的简单应用


#import "ViewController.h"

@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIImageView *imageVIew;

/** 线程*/
@property (nonatomic, strong) NSThread *thread;

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    
//    [self observer];
//    [self showImage];
//    [self timer];
    
    /**
     * 首先我们要让子线程不会在代码块执行完之后挂掉,所以要把线程变为全局
     */
    self.thread = [[NSThread alloc] initWithTarget:self selector:@selector(execute) object:nil];
    [self.thread start];
}

- (void)execute
{
    NSLog(@"线程开启");
    /*
     * 如果什么都不做,那么这个RunLoop没有timer,source,observer那么刚运行就会关闭
     */
    
    //给当前线程添加一个定时器那么就不会关闭了
//    [self timer];
    //也可以给当前线程添加一个source事件
//    [[NSRunLoop currentRunLoop] addPort:[NSPort port] forMode:NSDefaultRunLoopMode];
    //也可以添加一个observer事件
    [[NSRunLoop currentRunLoop] run];

    NSLog(@"----如果输出了说明NSRunLoop刚跑起来就结束了");
}

/*
 * RunLoop从表面意思来看就是说跑圈或者是说循环,但是真正在程序中的表现,就像是一个do-while循环,正是这个循环才让你的程序不至于一开始就死亡。
 * RunLoop一直在循环的监听处理各种事件。比如定时器事件,Sourse事件,Observer事件
 * 同时呢,RunLoop如果没有这些事件,那么RunLoop就会直接退出
 * RunLoop同时只能运行一种Mode,RunLoop有五种运行模式,但是只有两种是经常用到的,那就是DefaultMode和TrackingMode,DefaultMode下处理各种事件比如时钟,触摸事件,点击事件等大部分事件,而TrackingMode是RunLoop为了处理scrollView的滑动事件而产生的Mode,为的就是让在滑动过程中,不受其他事件的影响。所以说,如果想让某个事件在滑动的时候依旧能运行的话,那么就让这个事件处于TrackingMode
 * RunLoop 有两套框架,一套是CFRunLoopRef ,另一套是NSRunLoop,通过名字应该也知道CFRunLoopRef是基于C的一套框架,而NSRunLoop则是对CFRunLoopRef的一种封装,更加的面向对象。
 */


/*
 * 我们可以监听RunLoop的状态改变
 */
- (void)observer
{
    //这里创建一个observer观察的事件,系统给了两种创建方式,但是这一种明显更简单
    CFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler(CFAllocatorGetDefault(), kCFRunLoopAllActivities, YES, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {
        
        NSLog(@"-----RunLoop的状态----%zd",activity);
    });
    
    //创建之后需要添加观察者:监听RunLoop的状态
    
    CFRunLoopAddObserver(CFRunLoopGetCurrent(), observer, kCFRunLoopDefaultMode);
    /*
     * CF的内存管理 (CoreFoundation)
     * 1.凡是带有create、copy、retain等字眼的函数,创建出来的对象,都需要在最后做一次release
     * 2.release函数:(CFRelease(对象))
     */
    //释放Observer
    CFRelease(observer);
    
    /*
     * 打印为:1 - 2 - 4 - 2 - 4 - 2 - 4 - 32 - 64 - 2 - 4 ……
     * 从打印我们可以看出,RunLoop是一个循环,开始进入RunLoop之后就开始处理Timer事件
        然后处理Source0事件再通知下RunLoop要睡眠了。然后就进入睡眠状态,开发者可以通过监听这些状态来做一些事件
     */
}

/**
 * 解决定时器在滚动的时候不执行的问题
 */
- (void)timer
{
    /*
     * 平常我们使用这种方法启动定时器,这种方式启动返回的定时器,已经自动被添加到当前的RunLoop中(一般在主线的RunLoop如果没有开启子线程的RunLoop的话),而且Mode是NSDefaultRunLoopMode,在这种方式下,如果我们滑动scrollView,这个计时器就会暂停
     */
    NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:@selector(run) userInfo:nil repeats:YES];
    
    /*
     * 这种方式需要你来把定时器添加到RunLoop中才会工作
     */
//    NSTimer *timer = [NSTimer timerWithTimeInterval:2.0 target:self selector:@selector(run) userInfo:nil repeats:YES];
    
    /*
     * 如果想要在滚动的时候也能滑动的话,那么就修改Mode为UITrackingRunLoopMode
     * 在苹果中NSRunLoopCommonModes包括NSDefaultRunLoopMode和UITrackingRunLoopMode模式
     */
//    [[NSRunLoop currentRunLoop] addTimer:timer forMode:UITrackingRunLoopMode];
    
    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
    
}

- (void)run
{
    NSLog(@"---run-----%@", [NSThread currentThread]);
}

/**
 * 为了提升用户的体验,不至于用户在滑动页面的时候感觉到卡顿,我们可以把耗时操作放在NSDefaultRunLoopMode中进行操作
 * 比如图片的渲染就是一个比较耗时的操作,我们让图片再用户停止滑动的时候再进行渲染
 */
- (void)showImage
{
    [self.imageVIew performSelector:@selector(setImage:) withObject:[UIImage imageNamed:@"share"] afterDelay:3 inModes:@[NSDefaultRunLoopMode]];
}

/*
 * 我们可以让子线程长存,进行某些活动
 */
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    [self performSelector:@selector(test) onThread:self.thread withObject:nil waitUntilDone:NO];
}

- (void)test
{
    NSLog(@"----test----%@", [NSThread currentThread]);
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值