iOS Runloop面试题(AFNetworking 中如何运用 Runloop?)

AFNetworking 中如何运用 Runloop?

AFURLConnectionOperation 这个类是基于 NSURLConnection 构建的,其希望能在后台线程接收 Delegate 回调。为此 AFNetworking 单独创建了一个线程,并在这个线程中启动了一个 RunLoop:

+ (void)networkRequestThreadEntryPoint:(id)__unused object {

    @autoreleasepool {

        [[NSThread currentThread] setName:@"AFNetworking"];

        NSRunLoop *runLoop = [NSRunLoop currentRunLoop];

        [runLoop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];

        [runLoop run];

    }

}

AFNetworking 2.0的常驻线程为什么一开始要自动释放池

Using Autorelease Pool Blocks

Each thread in a Cocoa application maintains its own stack of autorelease pool blocks. If you are writing a Foundation-only program or if you detach a thread, you need to create your own autorelease pool block.

当新建线程的时候,需要使用自动释放池。并且设计到Cocoa编程在合适的地方也要设置自动释放池。

- 为了在释放池块后,立即释放对象

- 开启新的线程时,需要维护自动释放池栈

@autoreleasepool {

        [[NSThread currentThread] setName:@"AFNetworking"];

        NSRunLoop *runLoop = [NSRunLoop currentRunLoop];

        [runLoop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];

        [runLoop run];

    }

所以上面的代码逻辑是给子线程创建runloop和维持线程等待消息。自动释放池存在的逻辑不是为了释放对象,而是新建线程需要**维护自动释放池栈**。参考整个app的main函数app启动

+ (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 中。

你可能感兴趣的:(iOS Runloop面试题(AFNetworking 中如何运用 Runloop?))