为什么块对象不像NSObject那样以dealloc方式释放?

时间:2014-08-27 16:29:42

标签: ios objective-c memory-management objective-c-blocks

以下是说明问题的代码段

__weak id ptr = nil;
__weak id ptr2 = nil;
@autoreleasepool {
    void (^block)(void) = [^{
        NSLog(@"hahaha");
    } copy];
    block();
    [[(id)block rac_willDeallocSignal] subscribeCompleted:^{
        NSLog(@"block will dealloc");
    }];
    ptr = block;
    int blockRetainCount = CFGetRetainCount((__bridge CFTypeRef)block);

    NSObject *obj = [[NSObject alloc] init];
    [obj.rac_willDeallocSignal subscribeCompleted:^{
        NSLog(@"Obj dealloc");
    }];
    ptr2 = obj;
    int objRetainCount = CFGetRetainCount((__bridge CFTypeRef)obj);
    NSLog(@"oK");
}
NSLog(@"after pool %@ %@" , ptr, ptr2);

当我运行此代码段时,我会看到Obj dealloc打印到控制台但不是block will dealloc。在自动释放池之后,我将看到ptr仍然包含对块的有效refence,而ptr2已按预期正确重置为nil。为什么会出现这种差异?块什么时候才能完全被释放?

1 个答案:

答案 0 :(得分:3)

多个问题应该说服你不要尝试这样的事情:

一,CFGetRetainCount不保证在ARC存在的情况下返回任何有意义的内容。

二,无法保证块完全使用保留计数。不捕获任何变量的块被分配为静态变量;复制,保留等等对它们一无所知,它们永远不会被分配或取消分配。

第三,不能保证任何块在解除分配时都会调用dealloc。并且无法保证它会在下一个OS或iOS版本中发生。