iOS 开发NSRunLoop和AutoreleasePool详解

运行循环(消息循环)和自动释放池的关系图解

这里写图片描述

  • 运行循环在 iOS 开发中几乎不用,但是概念的理解却非常重要。

  • 自动释放池的创建和销毁
    运行循环检测到事件并启动后,就会自动创建自动释放池.一次完整的运行循环结束之前,自动释放池就会被销毁.

  • 作用:
    保证程序不退出。
    负责监听所有事件,例如:手势触摸,时钟触发,网络加载数据完成等。

  • 特性:
    没有事件时,会休眠(省电),一旦监听到事件,会立即响应。
    每一个线程都有一个 runloop,但是只有主线程的 runloop 会默认启动。子线程的运行循环默认是不启动的。

//经典面试题:
    long largeNumber = 1000000;

//    for (int i = 0; i < largeNumber; ++i) {
//        // 相当于创建一次就销毁一次,保证了内存平衡
//        NSString *str = @"Hello World";
//        str = [str stringByAppendingFormat:@" - %d", i];
//        str = [str uppercaseString];
//    }

    /*
     1.内存瞬间暴涨
     2.因为for循环的速度非常快,CPU来不及处理内存
     3.解决办法 : 在for循环的开始就创建自动释放池
     4.原理 : 出了自动释放池的作用域里面的对象就销毁了
     */
    for (int i = 0; i < largeNumber; ++i) {

        // 相当于创建一次就销毁一次,保证了内存平衡
        @autoreleasepool {
            NSString *str = @"Hello World";
            str = [str stringByAppendingFormat:@" - %d", i];
            str = [str uppercaseString];
        }
    }

主线程中使用 NSTimer

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    [self timerDemo];
}

// 主线程的消息循环默认开启的
#pragma mark - 主线程中使用 NSTimer
- (void)timerDemo  {

    NSTimer *timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(fireDemo) userInfo:nil repeats:YES];
    // 获取当前主线程的运行循环,把定时器添加进去
    // currentRunLoop : 获取当前主线程的运行循环
    // forMode : 是timer的运行模式
    // 运行循环也是要运行在一定的模式下的.这个模式默认就是kCFRunLoopDefaultMode.只有运行循环的模式和timer的运行模式保持一致,那么运行循环才能够检测到timer的事件
    // 提示 : 不同的UI交互,运行循环的模式会自动的发生变化
    // NSRunLoopCommonModes : 模式组,内部包含有多种模式,包含kCFRunLoopDefaultMode和UITrackingRunLoopMode
    // UITrackingRunLoopMode : 追踪模式,是苹果专门设计的为滚动视图准备的
    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
//    NSLog(@"%@",[NSRunLoop currentRunLoop].currentMode);
}

- (void)fireDemo  {
    // currentMode : 当前运行循环的模式
    NSLog(@"hello %@",[NSRunLoop currentRunLoop].currentMode);
}

子线程中使用 NSTimer

  • 子线程运行循环:
    子线程的运行循环默认是不启动的。
    启动运行循环后,如果不停止运行循环,不会执行后续的任何代码,会形成一个死循环。
    一旦停止了运行循环,后续代码能够执行,执行完毕后,线程被自动销毁。
// 子线程里面的消息循环默认不开启,因为子线程不需要处理UI事件
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event  {
    [self performSelectorInBackground:@selector(timerDemo) withObject:nil];
}
 //在子线程中使用NSTimer
- (void)timerDemo {
    // 创建定时器
    NSTimer *timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(fireDemo) userInfo:nil repeats:YES];
    // 把定时器添加到当前的线程的运行循环
    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
    // 需要手动的开启当前子线程的运行循环,这种开启的方式是个无法执行完的死循环
//    [[NSRunLoop currentRunLoop] run];
    //设置一个时限,让循环结束
    [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:3.0]];
    // 提问 : mark神马时候打印? 不会打印的,因为currentRunLoop是个死循环
    NSLog(@"mark");
}
- (void)fireDemo  {  NSLog(@"hello");  }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值