如何启动一个 NSRunLoop,并确保它有一个被清空的 NSAutoreleasePool?

Posted

技术标签:

【中文标题】如何启动一个 NSRunLoop,并确保它有一个被清空的 NSAutoreleasePool?【英文标题】:How do I start up an NSRunLoop, and ensure that it has an NSAutoreleasePool that gets emptied? 【发布时间】:2010-05-14 09:45:33 【问题描述】:

我有一个“同步”任务,它依赖于几个“子任务”,其中包括异步网络操作,但都需要访问单个 NSManagedObjectContext。由于NSManagedObjectContexts 的线程要求,我需要这些子任务中的每一个在同一个线程上执行。由于其中一些任务的处理量很大,我需要它们在后台线程上。

目前,我正在我的单例SyncEngine 对象的-init 方法中执行此操作来启动一个新线程:

[self performSelectorInBackground:@selector(initializeSyncThread) withObject:nil];

-initializeSyncThread 方法如下所示:

- (void)initializeSyncThread

    self.syncThread = [NSThread currentThread];
    self.managedObjectContext = [(MyAppDelegate *)[UIApplication sharedApplication].delegate createManagedObjectContext];
    NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
    [runLoop run];

这是为该线程启动NSRunLoop 的正确方法吗?有更好的方法吗?运行循环只需要处理“performSelector”源,它(及其线程)应该在进程的生命周期内存在。

在设置NSAutoreleasePool 时,我是否应该使用 Run Loop Observers 创建自动释放池并在每次运行后将其排空?

【问题讨论】:

【参考方案1】:

我不能 100% 确定这是解决您的问题的最有效方法,但我正在这样做......

由于异步网络操作可能需要不同的时间来完成(或超时),我使用实例变量(在本例中为名为 callComplete 的 BOOL)跟踪它们

当触发网络请求的代码启动时,我的NSURLConnection 消失了,这很神奇,我就这样等待调用完成。

while(!callComplete && [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]])
    // Here you can perform other checks, like making sure the method isn't running forever (with a timeout variable)
    // Just set callComplete to YES when done

【讨论】:

【参考方案2】:

关于NSAutoreleasePool,我只是在后台运行的选择器的开头创建一个。然后在 Run Loop 完成后(并且我的调用完成)我在返回之前像往常一样释放。

【讨论】:

我有 7-8 个方法(最终可能会有更多)需要在后台线程上自动释放池。如果有办法设置它并将其从运行循环本身中排出(就像 CocoaTouch 如何为主线程做的那样),那肯定会更可取。 我认为您可以使用运行循环观察器来了解它何时处理完事件。有关详细信息,请查看 Apple 文档。

以上是关于如何启动一个 NSRunLoop,并确保它有一个被清空的 NSAutoreleasePool?的主要内容,如果未能解决你的问题,请参考以下文章

[iOS]浅谈NSRunloop工作原理和相关应用

NSRunLoop 和 NSAutoreleasePool,它们是如何交互的?

NSRunLoop的进一步理解

XCTest 中的 IOS -NSRunLoop:如何让运行循环在单元测试中工作?

UIScrollView 在滚动时暂停 NSTimer

NSURLConnection和NSRunLoop