I got confused in the life of a block under ARC. I wrote a unit test to demonstrate what bothers me.
- (void)testBlock { NSObject *testObject = [[NSObject alloc] init]; CompletionBlock testBlock = ^{ NSLog(@"%@", testObject); }; XCTAssertNotNil(testObject, @"testObject should not be nil"); __weak NSObject *weakTestObject = testObject; @autoreleasepool { testObject = nil; } XCTAssertNotNil(weakTestObject, @"testObject should be retained by testBlock"); @autoreleasepool { testBlock = nil; }
I assume this behavior has something to do with how the blocks are stored on the stack / heap.
Update!
Setting a block to nil does not release the block as I expected, because it is on the stack and will not be released until it goes out of scope. Forcing a block to exit the scope corrects my test. Updated code below.
- (void)testBlock { NSObject *testObject = [[NSObject alloc] init]; __weak NSObject *weakTestObject = testObject; @autoreleasepool { CompletionBlock testBlock = ^{ NSLog(@"%@", testObject); }; XCTAssertNotNil(testBlock, @"testBlock should not be nil"); XCTAssertNotNil(testObject, @"testObject should not be nil"); testObject = nil; XCTAssertNotNil(weakTestObject, @"testObject should be retained by testBlock");
objective-c objective-c-blocks
CrimsonChris
source share