简体   繁体   中英

Is @autoreleasepool still required for modern iOS 8 NSOperation usage?

I've read through Concurrency Programming Guide

In the guide the text states that GCD dispatch queues define their own @autoreleasepool pools and mentions that it's still recommended to define one at a per dispatch level, yet for NSOperation nothing is said and the example code provided by Apple also does not show usage of the @autoreleasepool structure. The only place where @autoreleasepool is vaguely mentioned in the context of NSOperation is in the Revision History,

2012-07-17 - Removed obsolete information about autorelease pool usage with operations.

Looking at sample code available online, for ex. http://www.raywenderlich.com/19788/how-to-use-nsoperations-and-nsoperationqueues is making usage of @autoreleasepool in the implementations of NSOperations based objects, for example:

@implementation ImageDownloader

- (void)main {
    @autoreleasepool {
      ...
    }
}     
@end
  1. How should I be implementation modern NSOperation objects?
  2. What was the update Apple are referring to from 2012-07-17 ?

If you are deriving from NSOperation and implementing the main method, you do not need to set up an autorelease pool. The default implementation of the start method pushes an NSAutoReleasePool , calls main and then subsequently pops the NSAutoReleasePool . The same goes for NSInvocationOperation and NSBlockOperation , which share the same implementation of the start method.

The following is an abridged disassembly of the start method for NSOperation . Note the calls to NSPushAutoreleasePool, then a call to main followed by a call to NSPopAutoreleasePool:

Foundation`-[newMyObj__NSOperationInternal _start:]:
0x7fff8e5df30f:  pushq  %rbp

...

0x7fff8e5df49c:  callq  *-0x16b95bb2(%rip)        ; (void *)0x00007fff8d9d30c0: objc_msgSend
0x7fff8e5df4a2:  movl   $0x1, %edi

; new NSAutoreleasePool is pushed here
0x7fff8e5df4a7:  callq  0x7fff8e5df6d6            ; NSPushAutoreleasePool

... NSOperation main is called

0x7fff8e5df6a4:  callq  *-0x16b95dba(%rip)        ; (void *)0x00007fff8d9d30c0: objc_msgSend
0x7fff8e5df6aa:  movq   %r15, %rdi

; new NSAutoreleasePool is popped here, which releases any objects added in the main method
0x7fff8e5df6ad:  callq  0x7fff8e5e1408            ; NSPopAutoreleasePool

Here is a snapshot of some example code running

  1. MyObj is allocated in the main method and I make sure the object must be autoreleased
  2. main returns to _start , and the following image shows a stack trace with MyObj dealloc being called by the current autorelease pool, popped inside _start

调用NSPopAutoreleasePool时释放调用堆栈显示对象

For reference, this is the example code I used to verify the behavior:

#import <Foundation/Foundation.h>

@interface MyObj : NSObject
@end

@implementation MyObj

- (void)dealloc {
    NSLog(@"dealloc");
}

@end

@interface TestOp : NSOperation {
    MyObj *obj;
}

@end

@implementation TestOp

- (MyObj *)setMyObj:(MyObj *)o {
    MyObj *old = obj;
    obj = o;
    return old;
}

- (void)main {
    MyObj *old = [self setMyObj:[MyObj new]];
    [self setMyObj:old];
}

@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...
        NSLog(@"Hello, World!");

        NSOperationQueue *q = [NSOperationQueue new];
        TestOp *op = [TestOp new];
        [q addOperation:op];

        [op waitUntilFinished];
    }
    return 0;
}

Grand Central Dispatch similarly manages autorelease pools for dispatch queues, per the Concurrency Programming Guide :

If your block creates more than a few Objective-C objects, you might want to enclose parts of your block's code in an @autorelease block to handle the memory management for those objects. Although GCD dispatch queues have their own autorelease pools, they make no guarantees as to when those pools are drained. If your application is memory constrained, creating your own autorelease pool allows you to free up the memory for autoreleased objects at more regular intervals.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM