2011-01-11 72 views
0

我有一個UITextField,並在委託類中有一個UITableView。代碼如下:內存泄漏 - 儀器,Objective-C

- (BOOL) textField: (UITextField *)theTextField shouldChangeCharactersInRange: (NSRange)range replacementString: (NSString *)string {  
    value = [[theTextField.text stringByReplacingCharactersInRange:range withString:string] retain]; 

    [valueTable reloadData]; 

    return YES; 
} 

「value」是在我的類的頂部聲明爲「NSString * value;」的NSString。和「valueTable」只是一個UITableView。當我測試內存泄漏時,出現「value = [[theTextField.text stringByReplacing ...」上的「100%」內存泄漏,我嘗試刪除該行上的「retain」。然而,後來當我呼籲「價值」時,它是零,這是不好的。

那麼我該如何解決內存泄漏?什麼是內存泄漏?謝謝!

回答

1

正在泄漏的內存是由value指向的內存。

每次您的文本字段發生變化時,方法stringByReplacingCharactersInRange...都會返回一個自動發佈的NSString對象。你保留它是正確的,所以它不會被釋放。問題在於你現在擁有自己的記憶。 (您通過保留它來擁有該NSString。)

下次調用該方法時,當用戶更改該字段中的文本時,您將value指向完全不同的內存位置。你保留的原始記憶仍然存在,並將繼續保持下去。 (因爲你從來沒有發佈過。)

這是非常重要匹配任何retain方法調用與相關release。你可以這樣做既:

... 
if (value) { 
    [value release]; 
} 
value = ...; 
... 

OR

您可以定義NSString *value爲你的類的屬性,如:

@property (nonatomic, retain) NSString *value); 

/* Implementation file */ 
@synthesize value; 

然後只需使用:

... 
self.value = ...; 
... 

另外,因爲你總是會保留mem這種方法被稱爲ORY後,你需要釋放value當你的類被釋放,在另一個答案被提及:

- (void)dealloc { 
    // Only do *one* of the two following releases 

    // (1) If you're not using properties: 
    [value release]; 

    // (2) If you are using properties: 
    self.value = nil; 

    [super dealloc]; 
} 

編輯:這聽起來像你一定要閱讀蘋果的內存管理指南繼續之前: http://developer.apple.com/library/mac/#documentation/cocoa/conceptual/MemoryMgmt/MemoryMgmt.html

+1

第一個例子中的'if(value)`語句是不必要的。如果`value`是`nil`,那麼`[value release];`什麼都不會做,如果不是,它會被釋放。 – kubi 2011-01-11 18:28:37

0

稍後,您應該在完成後發佈value。例如,你可以釋放它在代理的dealloc方法時:

- (void)dealloc { 
    [value release]; 
    // other memory management code... 
    [super dealloc]; 
} 

看到蘋果的內存管理文檔。

+0

這是唯一正確的,如果你假設stringByReplacingCharactersInRange方法被調用一次。例如,如果該方法被調用4次,那麼您將該內存泄漏了3次,並且僅適當地釋放它一次。 (當他的課程被釋放時) – 2011-01-11 18:28:43

0

正如其他人所說的,問題出在下面一行:

value = [[theTextField.text 
     stringByReplacingCharactersInRange:range withString:string] retain]; 

此代碼的問題在於,在分配新值之前,您不會釋放舊值value。代碼更改爲以下應修復泄漏,只要有其他地方沒有其他不可預見的問題:

- (BOOL)textField:(UITextField *)theTextField 
     shouldChangeCharactersInRange:(NSRange)range 
      replacementString:(NSString *)string { 

    NSString *newValue = [[theTextField.text 
     stringByReplacingCharactersInRange:range withString:string] retain]; 
    [value release]; 
    value = newValue; 

    [valueTable reloadData]; 

    return YES; 
} 

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