为什么传递给块的变量没有被释放?

时间:2012-07-18 17:07:46

标签: objective-c

我已经测试了以下代码。

// Employee.h

@interface Employee : NSObject
@property(nonatomatic, copy) void (^print)(void);
@end

// Employee.m

@implementation Employee
@synthesize print = _print;

- (void)dealloc {
    [_print release];
    [super dealloc];
}

@end

// main.m

int main() {

    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
    Employee* john = [[[Employee alloc] init] autorelease];

    john.print = ^{
        NSLog(@"block test %@", john);
    };

    [pool drain];
}

在这种情况下,不会调用变量“john”的dealloc。 但是,如果我不记录john变量(就像NSLog(@“块测试”)),那么它的dealloc被调用。 怎么会错?

2 个答案:

答案 0 :(得分:2)

它是循环引用,它将阻止在引用计数内存管理系统中释放受影响的实例。

根据文件

  

在手动引用计数环境中,使用局部变量   复制块时,将保留块内的内容。

http://developer.apple.com/library/ios/documentation/cocoa/Conceptual/Blocks/Articles/bxVariables.html#//apple_ref/doc/uid/TP40007502-CH6-SW3

当块被复制到john时,

print被保留,因此john通过print变量保留了自己。即使john将被池的排放释放,引用计数也永远不会达到零,dealloc永远不会被调用。

答案 1 :(得分:0)

正如tia所说,你在这里有一个保留周期。

以下是摆脱它的解决方案:

int main() {

    NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
    Employee* john = [[[Employee alloc] init] autorelease];

    Employee* __weak weakjohn = john; // weak reference to john, to be used in the block.
    john.print = ^{
        NSLog(@"block test %@", weakjohn);
    };

    [pool drain];
}