为nsoperationqueue正确使用autorelease

为nsoperationqueue正确使用autorelease

本文介绍了如何为nsoperationqueue正确使用autoreleasepool的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个正在重构的应用程序,我刚刚实现了多线程,以便UI可以更流畅地运行.在iphone模拟器中,我没有泄漏,但是在运行iOS 4.2的iPhone 3G上进行测试时,我发现了内存泄漏.我已经做了很多工作,寻找使用操作队列实现自动释放池的正确方法,我们将不胜感激.

I have an app that I am refactoring and I just implemented multithreading so that the UI may run smoother. In the iphone simulator I don't get any leaks but testing on my iPhone 3G running on iOS 4.2 I get a memory leak. I have done a lot of searching for the correct way to implement an autoreleasepool with an operationqueue, help will be greatly appreciated.

我已经在自己的视图控制器中创建了一个nsoperationqueue

I have created an nsoperationqueue in my viewcontroller as such

- (void)loadData
{
  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
  NSOperationQueue *queue = [NSOperationQueue new];  // creates multithread for loading data without slowing UI
  NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(firstRun) object:nil];

  [queue addOperation:operation];
  [operation release];
  [queue release];
  [pool release];
}

推荐答案

首先,您不应该只是创建然后释放队列.将该队列作为类的ivars创建,然后在视图控制器消失时将其释放(您还可以取消任何挂起的操作并取消/等待任何正在运行的操作完成),这是更自然的选择.

First, you shouldn't just create and then release the queue. It's more natural to create that queue as one of your class's ivars and then release it when your view controller goes away (you can also cancel up any pending operations and cancel/wait for any running operations to complete).

第二,您不需要用于创建操作并将其添加到队列中的方法中的自动释放池,因为该方法是从主线程中调用的.相反,您需要对象实际调用的方法中的自动释放池(这可能是在另一个线程上运行的).

Second, you don't need the autorelease pool in the method that creates the operation and adds it in the queue since that method is being called from the main thread. Instead, you need the autorelease pool from the method your object actually calls (this is what may be running on another thread).

因此,您可能会遇到以下情况(假设您将队列命名为ivar queue _):

So, you might have the following (assuming you name your queue ivar queue_):

- (void)viewDidLoad
{
  [super viewDidLoad];

  if( !queue_ ) queue_ = [[NSOperationQueue alloc] init];
  // other view loading code
}

- (void)loadData
{
  NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(firstRun) object:nil];
  [queue_ addOperation:operation];
  [operation release];
}

- (void)firstRun
{
  // Here we may run on another thread, so 1) we need an autorelease pool; and
  // 2) we need to make sure we don't do anything that requires a runloop
  NSAutoreleasePool* threadPool = [NSAutoreleasePool new];

  // do long-running things

  [threadPool drain];
}

- (void)dealloc
{
  if( queue_ ) {
    [queue_ setSuspended:YES];
    [queue_ cancelAllOperations];
    // you need to decide if you need to handle running operations
    // reasonably, but don't wait here because that may block the
    // main thread
    [queue_ release];
  }
  // other dealloc stuff
  [super dealloc];
}

您还可以按需初始化队列,因此,无需在viewDidLoad中进行初始化,而是检查队列是否存在,并在需要添加操作的任何地方进行初始化(如有必要).可以将其包装在其自身的方法调用中,但是由于队列非常轻巧,因此这里实际上不需要进行延迟初始化.

You could also initialize your queue on demand, so instead of initializing in viewDidLoad, check for its existence and initialize if necessary anywhere you'd add an operation. This might be wrapped in a method call of its own, but lazy initialization here probably isn't really necessary as queues are pretty light-weight.

这篇关于如何为nsoperationqueue正确使用autoreleasepool的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-05 06:56