0

次のコードをテストしました。

// 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(@"block test") のように)、dealloc が呼び出されます。何が間違っているでしょうか?

4

2 に答える 2

2

これは循環参照であり、影響を受けるインスタンスが参照カウント メモリ管理のシステムで割り当て解除されるのを防ぎます。

ドキュメントによると

手動で参照カウントされる環境では、ブロック内で使用されるローカル変数は、ブロックがコピーされるときに保持されます。

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

johnブロックが にコピーされたときに保持されたので、変数を介して保持されているprintようです。プールのドレインによって解放されても、参照カウントがゼロになることはなく、呼び出されることもありません。johnprintjohndealloc

于 2012-07-18T17:23:57.243 に答える
0

ティアが言ったように、ここには保持サイクルがあります。

これを取り除くための解決策は次のとおりです。

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];
}
于 2012-07-18T17:33:02.950 に答える