2012-07-18 27 views
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。 但是,如果我不記錄約翰變量(就像NSLog(@「block test」)),那麼它調用dealloc。 會出現什麼問題?

回答

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將永遠不會被調用。

+0

謝謝!我還有一個問題。當john.print被執行時,約翰被保留了嗎? – Daoxin 2012-07-19 05:54:23

+0

@Daoxin當'john'被自動保留的時候,'print'屬性被分配。編譯器會自動執行此操作,以確保在執行塊中的代碼之前不會解除分配「john」,這可能稍後會過時。在異步回調模塊的情況下。 – tia 2012-07-19 09:05:04

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]; 
} 
相關問題