我对ARC下块的生命周期感到困惑。我编写了一个单元测试来演示我的疑惑。
我猜测这种行为与代码块在堆栈/堆上的存储方式有关。
更新!
将代码块设置为nil并不会像我期望的那样释放它,因为它在堆栈上,并且只有在超出作用域时才会被释放。强制使代码块超出作用域可以解决我的测试问题。下面是更新后的代码。
- (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;
}
//THIS IS THE FAILING TEST CASE
XCTAssertNil(weakTestObject, @"testObject should have been released when testBlock was released");
}
我猜测这种行为与代码块在堆栈/堆上的存储方式有关。
更新!
将代码块设置为nil并不会像我期望的那样释放它,因为它在堆栈上,并且只有在超出作用域时才会被释放。强制使代码块超出作用域可以解决我的测试问题。下面是更新后的代码。
- (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");
//testBlock goes out of scope here
}
XCTAssertNil(weakTestObject, @"testObject should have been released when testBlock was released");
}
copy
,但我相当确定我所做的只是将该块添加到堆栈中,而不是仅仅在堆栈上操作。块在许多方面都像对象引用,这样的东西确实会让你感到困惑。 - CrimsonChris