2011-01-11 18 views
0

私はUITextFieldを持っており、デリゲートクラスには私はUITableViewを持っています。ここにコードはあります:メモリリーク - Instruments、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オブジェクトを返しています。あなたはそれを保持することが正しいので、割り当てを解除しません。問題は、今どこかで自分の記憶を所有しているということです。

このメソッドが呼び出されたときに、ユーザーがそのフィールドのテキストを変更すると、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]; 
} 

編集:それは間違いなくAppleのメモリ管理ガイドをお読みくださいますように聞こえる続行する前に: http://developer.apple.com/library/mac/#documentation/cocoa/conceptual/MemoryMgmt/MemoryMgmt.html

+1

最初の例の 'if(value)'ステートメントは不要です。 'value'が' nil'ならば '[value release];は何もしません。そうでなければ解放されます。 – kubi

+0

非常に真です。それは単に私がラインに沿ってどこかで拾った習慣です。 –

0

これが完了したら、後でvalueをリリースする必要があります。たとえば、デリゲートのdealloc方法で時にそれを解放することができます

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

は、メモリ管理上のAppleのドキュメントを参照してください。

+0

あなたはstringByReplacingCharactersInRangeメソッドが一度だけ呼び出されると仮定している場合、これが唯一の正しいです。たとえば、そのメソッドが4回呼び出された場合、そのメモリを3回リークさせて、1回だけ適切に解放します。 (彼のクラスが割り当て解除されたとき) –

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]; 
} 
関連する問題