2010-02-28 146 views
2

我以爲我得到可可內存管理的竅門,但顯然我有很多東西要學。內存管理問題

看看這個類我寫道:

Word.h

#import <UIKit/UIKit.h> 


@interface Word : NSObject { 
    NSString *word; 
    NSMutableArray *wordArray; 
} 

@property (nonatomic ,retain) NSString *word; 
@property (nonatomic ,retain) NSMutableArray *wordArray; 

@end 

Word.m

#import "Word.h" 


@implementation Word 

@synthesize word, wordArray; 

- (void)setWord:(NSString *)aWord { 
    NSMutableArray *newValue = [[NSMutableArray alloc] init]; 
    self.wordArray = newValue; 
    [newValue release]; 

    for (int i = 0 ;i < [aWord length] ;i++) { 
     NSString *character = [[NSString alloc] init]; 
     character = [NSString stringWithFormat:@"%C",[aWord characterAtIndex:i]]; 
     [wordArray addObject:character]; 
     //[character release]; 
    } 
} 

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

@end 

正如你所看到的,當我設置字符串時,我正在填充一個數組。我通過拉出字符串的字符並將它們放入一個新的分配字符串中來對此進行for循環。 然後我把該字符串放在數組中,然後我必須釋放字符串。 它在這裏我做錯了,因爲我釋放了我放入數組的值。當後來我試圖使用數組時,它就消失了。

我應該怎麼辦?讓「角色」成爲財產並在dealloc中釋放它是錯誤的,因爲它只是暫時的。

回答

6

首先,您不需要指定新的NSStringcharacter,因爲您立即用另一個對象覆蓋它。記住,它是一個指針,所以當你指定它的時候,你並沒有改變它指向的對象,只是把它指向另一個對象。因此,當我們丟失了指向它的指針時,您分配並最初分配給character的對象將在下一行中泄漏。

現在,stringWithFormat返回一個自動釋放字符串,然後character指向。這個對象不應該被你釋放,但這就是在註釋掉的行中發生的事情。這樣循環會更好:

for (int i = 0 ;i < [aWord length] ;i++) { 
     NSString* character = [NSString stringWithFormat:@"%C",[aWord characterAtIndex:i]]; 
     [wordArray addObject:character]; 
} 
+0

所以autorelease池被耗盡,當類的實例死了,我可以確保autorelease不會太快釋放我的對象? – Oscar 2010-02-28 10:11:34

+2

自動釋放池在運行循環中釋放,即在正常代碼之外。它不會在你的一個方法中觸發。 編輯:如果你使用後臺線程,否則這可能是一個問題,你需要設置一個線程本地autorelease池正是因爲這個原因。但這不是問題。 – 2010-02-28 10:20:59

+0

好吧,謝謝你的幫助:) – Oscar 2010-02-28 10:23:23

3

除了內存管理的關注,你知不知道你已經覆蓋了setter函數爲word財產?

當你@synthesize你的話的財產,都在幕後生成的setter和getter方法等有已經爲- (void)setWord:(NSString *)aWord;功能和- (NSString *)word;可以在Objective-C primerProgramming Language documentation瞭解這一點。

由於您已經創建了(void)setWord:(NSString *)aWord;函數,因此這將覆蓋生成的setter。由於您實際上未設置word變量,因此您的資產已「破損」。

舉個例子,也許把它改寫爲:

#import "Word.h" 

@implementation Word 

@synthesize word, wordArray; 

- (void)setWord:(NSString *)aWord { 
    // set the word iVar 
    if (aWord != word) { 
     [aWord retain]; // I prefer [aWord copy]; 
     [word release]; 
     word = aWord; 
    } 

    NSMutableArray *newValue = [[NSMutableArray alloc] init]; 

    for (int i = 0 ;i < [aWord length] ;i++) { 
     NSString *character = [NSString stringWithFormat:@"%C",[aWord characterAtIndex:i]]; 
     [wordArray addObject:character]; 

    } 
    // Now that you have created the newArray, set it to the property 
    self.wordArray = newValue; 
    [newValue release]; 
} 

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

@end 

編輯

爲什麼我寫的,我首選[aWord copy]超過[aWord retain]?因爲我會宣佈屬性爲copy而不是retain

可變性可能是一種痛苦。讓我們假設代替傳遞NSString*aWord而不是傳遞NSMutableString*。這是可能的,因爲NSMutableStringNSString的子類。讓我們假設程序的另一部分改變了這個字符串的值(畢竟它是可變的)。現在,我們從外部改變了Word類的屬性。這打破封裝。

對集合類使用@property (copy)…是有意義的。

您可以閱讀一個很好的答案here

+0

好點。不過,我不明白你的評論('我更喜歡[aWord copy]')。財產聲明說'保留'所以它應該保留,對吧? – 2010-02-28 14:58:04

+0

斯蒂芬,我擴大了我的答案。 – Abizern 2010-02-28 15:17:47

+0

這是非常有趣的,我從來沒有使用過的複製,因爲我從來沒有對它做過什麼。謝謝! – Oscar 2010-02-28 16:59:33