美文网首页
RunLoop理解

RunLoop理解

作者: 小强简书 | 来源:发表于2018-04-02 18:05 被阅读13次

    1.RunLoop概念
    是一个让线程能随时处理事件但是不退出的机制,它是一个对象,这个对象管理了其需要处理的事件和消息,并且提供了一个入口函数,线程执行了这个函数以后,就会处于这个函数内部 接收消息,等待,处理的循环中,这个这个循环结束,函数返回。
    2.RunLoop与线程的关系
    苹果不允许直接创建 RunLoop,它只提供了两个自动获取的函数:CFRunLoopGetMain() 和 CFRunLoopGetCurrent()。
    可以看出,线程和RunLoop是一一对应的,其关系是保存在一个全局的Dictionary中,线程创建的时候没有RunLoop,你如果不获取,它就一直没有,RunLoop的创建是在第一次获取的时候,RunLoop的销毁是在线程结束的时候,所以你只能在一个线程内部获取其RunLoop(主线程除外)

    3.RunLoop 的 Mode
    苹果公开提供的 Mode 有两个:
    1 NSDefaultRunLoopMode(kCFRunLoopDefaultMode)默认,空闲状态
    2 UITrackingRunLoopMode ScrollView滑动时

    同时苹果还提供了一个操作 Common 标记的字符串:kCFRunLoopCommonModes (NSRunLoopCommonModes),你可以用这个字符串来操作 Common Items,或标记一个 Mode 为 “Common”。使用时注意区分这个字符串和其他 mode name

    RunLoop其内部是一个 do-while 循环。当你调用 CFRunLoopRun() 时,线程就会一直停留在这个循环里;直到超时或被手动停止,该函数才会返回。

    4.AFNetworking

    + (void)networkRequestThreadEntryPoint:(id)__unused object {
        @autoreleasepool {
            [[NSThread currentThread] setName:@"AFNetworking"];
            NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
            [runLoop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];
            [runLoop run];
        }
    }
     
    + (NSThread *)networkRequestThread {
        static NSThread *_networkRequestThread = nil;
        static dispatch_once_t oncePredicate;
        dispatch_once(&oncePredicate, ^{
            _networkRequestThread = [[NSThread alloc] initWithTarget:self selector:@selector(networkRequestThreadEntryPoint:) object:nil];
            [_networkRequestThread start];
        });
        return _networkRequestThread;
    }
    

    RunLoop 启动前内部必须要有至少一个 Timer/Observer/Source,所以 AFNetworking 在 [runLoop run] 之前先创建了一个新的 NSMachPort 添加进去了。通常情况下,调用者需要持有这个 NSMachPort (mach_port) 并在外部线程通过这个 port 发送消息到 loop 内;但此处添加 port 只是为了让 RunLoop 不至于退出,并没有用于实际的发送消息。

    - (void)start {
        [self.lock lock];
        if ([self isCancelled]) {
            [self performSelector:@selector(cancelConnection) onThread:[[self class] networkRequestThread] withObject:nil waitUntilDone:NO modes:[self.runLoopModes allObjects]];
        } else if ([self isReady]) {
            self.state = AFOperationExecutingState;
            [self performSelector:@selector(operationDidStart) onThread:[[self class] networkRequestThread] withObject:nil waitUntilDone:NO modes:[self.runLoopModes allObjects]];
        }
        [self.lock unlock];
    }
    

    当需要这个后台线程执行任务时,AFNetworking 通过调用 [NSObject performSelector:onThread:..] 将这个任务扔到了后台线程的 RunLoop 中。

    保持RunLoop不退出的方法启动前内部必须要有至少一个 Timer/Observer/Source,AFNetworking中是持有一个NSMachPort,而SRWebSocket中是用dispatch_group_wait和dispatch_group_leave,单独创建一个NSRunLoop的分类

    相关文章

      网友评论

          本文标题:RunLoop理解

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