2011-03-17 74 views
0

嘿,我只是試圖讓事情100%清楚在我的腦海,關於iPhone的內存管理,我很確定我有一個很好的理解,雖然我不是100 %自信。瞭解@property內存管理

讓我們創建一個實例屬性,它是一個的NSArray:

@interface ExampleAppDelegate : NSObject { 
    NSArray *myArray; 
} 

@property (nonatomic,retain) NSArray *myArray; 

然後合成屬性,以便我們可以使用getter和setter方法:

@synthesize myArray; 

現在,這裏是我得到稍微困惑..說我們在外部類創建一個數組,並將其分配給我們的代表myArray:

appDelegate = (ExampleAppDelegate *)[[UIApplication sharedApplication] delegate]; 

NSArray *exampleArray = [[NSArray alloc] init]; 
appDelegate.myArray = exampleArray; 
[exampleArray release]; 

現在我們已經爲myArray分配了一個保留計數爲1,因爲它已經佔用了分配的exampleArray,因爲這樣我們將需要在委託dealloc內部調用release來讓myArray在代理被銷燬時不泄漏:

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

雖然如果我是分配myArray的,像這樣:

appDelegate = (ExampleAppDelegate *)[[UIApplication sharedApplication] delegate]; 
NSArray *exampleArray = [NSArray arrayWithObject:[NSString stringWithFormat:@"Hello world"]]; 
appDelegate.myArray = exampleArray; 

我就不是必需的,因爲內存管理是爲我處理,這樣做會在釋放分配給myArray的對象調用[myArray release];中的dealloc ?

+3

''[super dealloc]''應該是你的''dealloc''方法中的最後一個。 XCode很可能會抱怨,如果它不是最後一個。 – 2011-03-17 16:33:02

+0

感謝您的指點,我一直認爲這是無關緊要的 – Alex 2011-03-17 16:57:13

回答

1

你必須在兩種情況下發布myArraymyArray由您的班級「擁有」,因此如果不再需要myArray,則負責減少參考計數。分配給myArray的數組的分配方式無關緊要;每當你進行賦值時,合成的setter函數將增加數組的保留計數(因爲你這樣指定),所以你的類擁有對數組的引用,你必須在析構函數中補償它。

如果您已經使用了(nonatomic, copy),則同樣適用 - 在這種情況下,您的類將分配數組的副本,因此它也擁有該副本。

假如你使用(nonatomic, assign),你將不會擁有myArray,但在這種情況下,你永遠無法確定該陣列仍然存在,當你試圖使用它 - 它可能發生,你的程序的其他部分有已經發布了該陣列,並在此期間被釋放。因此,對於Objective C對象,除了具有普通舊C類型的屬性(例如NSInteger,這只是C中的整數數據類型之一的typedef)外,您不應在屬性規範中使用assign

+0

我看到我看到了,這對我來說已經解決了,謝謝,所以我們假設我一直在接收EXC_BAD_ACCESS,這很可能是因爲我在一個屬性上多次調用發佈,或者因爲我已經發布了它,然後嘗試稍後它已經發布時參考它? – Alex 2011-03-17 16:47:03

+0

@Alex:無論哪種方式,你都釋放了太多次。 :-D – kubi 2011-03-17 16:57:37

2

您仍然必須發佈myArray。我沒有看到在第一個任務和第二個任務之間保留行爲的任何區別,只有exampleArray的創建發生了變化。

在第一次分配中,您確實創建了一個未自動釋放的實例,在將其分配給您的屬性後,其保留計數爲2。在那一步之後,您發佈了一次,因此保留計數降至其中一個實例。

第二個賦值會導致保留計數爲2,在應用程序的下一個運行循環週期後自動降至1,原因是NSArray arrayWithObject確實會返回一個自動釋放的實例,如果您喜歡將來使用它。

+1

對。關鍵在於,如果你的綜合setter使用'retain'選項,你的'dealloc'需要調用'release'。 – 2011-03-17 16:28:01

+0

噢好吧,我推測是因爲在第二個示例中沒有使用alloc init創建exampleArray,因此不需要在對象上調用發佈? – Alex 2011-03-17 16:30:16

+0

希望我能接受你的答案,謝謝你的見解! – Alex 2011-03-17 16:57:35