RunLoop代码中的使用

33 阅读2分钟

记录 仅供学习使用。

摘自:juejin.cn/post/716749…

1. RunLoop在iOS中的落地使用细节

1.1 RunLoop和线程的关系

  • 在默认情况下, 线程执行完之后就会退出, 就不能再继续任务了. 这时我们需要采用一种方式来让线程能够不断地处理任务, 并不退出. 所以, 我们就有了RunLoop.
  1. 一条线程对应一个RunLoop对象, 每条线程都有唯一一个与之对应的RunLoop对象.
  2. RunLoop并不保证线程安全. 我们只能在当前线程内部操作当前线程的RunLoop对象, 而不能在当前线程内部去操作其他线程的RunLoop对象方法.
  3. RunLoop对象在第一次获取RunLoop时创建, 销毁则是在线程结束的时候.
  4. 主线程的RunLoop对象系统自动帮助我们创建好了(UIApplicationMain函数), 子线程的RunLoop对象需要我们主动创建和维护.
#import <UIKit/UIKit.h>
#import "AppDelegate.h"

int main(int argc, char * argv[]) {
    @autoreleasepool {
        return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
    }
}

1.1.1 RunLoop与常驻线程

  • 常驻线程
  • 指的就是那些不会停止,一直存在于内存中的线程。
  • 后台常驻线程测试代码:
- (void)viewDidLoad {
    // 创建线程,并调用run1方法执行任务 
    self.thread = [[NSThread alloc] initWithTarget:self selector:@selector(run1) object:nil]; 
    // 开启线程 
    [self.thread start];
}

- (void)run1 {
    // 这里写任务 
    NSLog(@"----run1-----");
    // 添加下边两句代码,就可以开启RunLoop,之后self.thread就变成了常驻线程,可随时添加任务,并交于RunLoop处理 
    [[NSRunLoop currentRunLoop] addPort:[NSPort port] forMode:NSDefaultRunLoopMode]; 
    [[NSRunLoop currentRunLoop] run];
    // 测试是否开启了RunLoop,如果开启RunLoop,则来不了这里,因为RunLoop开启了循环。 
    NSLog(@"未开启RunLoop");
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    // 利用performSelector,在self.thread的线程中调用run2方法执行任务 
    [self performSelector:@selector(run2) onThread:self.thread withObject:nil waitUntilDone:NO];
}
- (void)run2 {
     NSLog(@"----run2-----");
}

1.1.2 AFN2.0 和3.0的主要区别--去除常驻线程