4

在 Apple 的MVCNetworking示例代码中,NetworkManager该类包含此方法以在专用于网络活动的辅助线程中维护运行循环(以便NSURLConnection异步运行):

- (void)networkRunLoopThreadEntry
{
    while(YES) {
        NSAutoreleasePool *pool;
        pool = [[NSAutorelease alloc] init];
        [[NSRunLoop currentRunLoop] run];
        [pool drain];
    }
}

由于run如果没有附加到运行循环的源,该方法将立即退出,这看起来像一个无限while循环,如果当前没有附加到运行循环的 NSURLConnection ,它将无用地消耗 CPU 资源。

另一方面,为了保持运行循环处于活动状态,有人 建议在运行循环中安排一个空端口:

 - (void)networkRunLoopThreadEntry
 {
     NSAutoreleasePool *pool = [[NSAutorelease alloc] init];
     NSPort *port = [NSPort port];
     [[NSRunLoop currentRunLoop] addPort:port forMode:NSRunLoopCommonModes];
     [NSRunLoop run];
     [pool drain];
 }

但是,在这种情况下,我担心该run方法永远不会退出,这意味着池永远不会被耗尽,这意味着在辅助线程中分配和自动释放的所有对象都会泄漏。

那该怎么走呢?

(对于上下文,和其他许多人一样,我正在尝试将异步封装NSURLConnection在 aNSOperation中,这意味着它可以在主线程之外触发。此外,MVCNetworking 示例代码以及 WWDC 2010 会话Network Apps for iPhone OS,似乎建议拥有一个专用于网络传输的唯一辅助线程以防止主线程延迟。)

4

1 回答 1

6

CFRunLoopObserver您可以为活动创建一个kCFRunLoopBeforeWaiting并将其添加到运行循环。在观察者的标注中,释放旧池并创建一个新池。未经测试的例子:

static void resetPoolCallout(CFRunLoopObserverRef observer, CFRunLoopActivity activity, void *info) {
    NSAutoreleasePool **poolPointer = (NSAutoreleasePool **)info;
    [*poolPointer release];
    *poolPointer = [[NSAutoreleasePool alloc] init];
}

- (void)networkRunLoopThreadEntry {
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    NSPort *port = [NSPort port];
    [[NSRunLoop currentRunLoop] addPort:port forMode:NSRunLoopCommonModes];

    CFRunLoopObserverContext observerContext = {
        .version = 0,
        .info = (void*)&pool,
        .retain = NULL,
        .release = NULL,
        .copyDescription = NULL
    };
    CFRunLoopObserverRef observer = CFRunLoopObserverCreate(NULL, kCFRunLoopBeforeWaiting,
        true, 0, resetPoolCallout, &observerContext);
    CFRunLoopAddObserver(CFRunLoopGetCurrent(), observer, kCFRunLoopCommonModes);

    [[NSRunLoop currentRunLoop] run];

    CFRunLoopRemoveObserver(CFRunLoopGetCurrent(), observer, kCFRunLoopCommonModes);
    CFRelease(observer);

    [pool release];
}
于 2012-07-11T21:01:52.710 回答