2011-02-08 28 views
1

イメージを次の機能を使用してUITableViewCellにロードしています。しかし、私がUITableViewをスクロールするたびに、私はデバッガで私のアプリを実行すると、[pool release]でクラッシュする。これを解決するにはどうすればよいですか?前もって感謝します。メモリリークの問題

- (void) loadImage{ 

    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 

    imageURL = [imageURL stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding];  
    //NSLog(@"img url cell**** %@",imageURL); 
    self.image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:imageURL]]]; 
    //self.image = [NSData dataWithContentsOfURL:[NSURL URLWithString:imageURL]]; 

    [pool release]; 
} 
+0

なぜこの方法で自動解放プールを使用していますか?一般的には、自分のプールを任意に作成してリリースするべきではありません。 –

+0

NSAutoReleasePoolを追加しました。 _NSAutoreleaseNoPool():クラスUIImageのオブジェクト0x364d6b0は、プールなしで自動リースされました。ちょうどリークしました。 – Madhumitha

+0

プールがmain.mファイルでどのように処理されたかを調べるためにsuggstを使用しました。それと同じようにしています。どこかに欠けている[プール排水]があります。 –

答えて

0

まず、[プールリリース]の代わりに[プールドレイン]を使用することをお勧めします。 しかし、私は別の潜在的な問題をここで参照してください:あなたのコードによると、あなたは新しく作成されたautoreleaseプールの外でimageURLを最初に定義しました(imageURLのalloc/initは見えません。 )次に、imageURLを新しく割り当てられた自動解放された文字列[imageURL stringByAddingPercentEscapesUsingEncoding:...]に再割り当てします。最後にプールを解放すると、新しいimageURLが解放されます。最後には、以前に割り当てられたimageURLのリークがあります。この時点で、内側のオートリリースプールから抜け出すと、実行ループのautoreleaseは、解放されたimageURLを再度リリースしようとします(たとえば、完全に理解するにはコードを参照する必要があります)。

stringByAddingPercentEscapesUsingEncoding:の結果を別の名前(例:myImageURL)に割り当てることはできますか?

+0

この回答を「役に立たない」とマークしたコメントだけ:このコードを実行し、それが動作するかどうか教えてください: NSString * mystr; - (void)test { \t NSLog(@ "Mystr =%@"、mystr); } - (BOOL)アプリケーション:(のUIApplication *)アプリケーションdidFinishLaunchingWithOptions:(NSDictionaryの*)launchOptions { \t \t mystr = [NSStringのstringWithString: "AA" @]。 \t NSAutoreleasePool * p = [[NSAutoreleasePool alloc] init]; \t mystr = [mystr stringByAppendingString:@ "BB"]; \t [pリリース]; \t \t [self performSelector:@selector(test)withObject:nil afterDelay:1.0]; } 次に、[pリリース]を削除するか、mystr2にBBを割り当てます。 – viggio24

5

NSAutoreleasePoolを使用しているということは、ロードイメージがメインスレッドではないスレッドで実行されていると思います。これは正しいです?その場合は、この非メインスレッドでUIKit呼び出し(self.image = ...)を行います。これは、発生しているクラッシュの可能性のあるソースです。 UIKitはスレッドセーフではないため、すべてのUIKitの更新はメインスレッドで行う必要があります。交換してみてください:私はセッターの名前を推測している

[self performSelectorOnMainThread:@selector(setImage:) withObject:[UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:imageURL]]] waitUntilDone:YES]; 
によって

self.image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:imageURL]]]; 

お知らせがsetImageです、あなたはセッターセレクタは、異なる名前を持っている場合は修正する必要があるかもしれません。

+0

はい。loadImageを別のスレッド([NSThread detachNewThreadSelector:@selector(loadImage)toTarget:self withObject:nil];)として呼び出しています。だから私は@ selector(setImage:)のための別のコードを記述する必要があります..? – Madhumitha

+0

イメージを設定するメソッドを作成するか、@ synthesizeによって作成されたメソッドを使用できます。 @synthesizeは各プロパティのgetterメソッドとsetterメソッドを作成します(指定しない限り)。名前の衝突に注意して、@synthesizeはsetImageを作成します:したがって、プロパティを設定する独自のメソッドを作成する場合は、setImage:という名前を付けたり、@property定義で "setter"を定義したりしないでください。 – fsaint

+0

performSelectorOnMainThread:呼び出しに対して - (void)mySetImage:(UIImage *)im {self.image = im}を定義し、このセレクタ(@selector(mySetImage :))を使用してください。 – fsaint

0

ここではかなり間違っています。

まず、自動解放プールの必要性は、あなたがメインスレッドでこの作業をしていないことを明らかに示しています。 UIKitはスレッドセーフではありません。どのUI作業もメインスレッド上で実行する必要があります。クラッシュなど、未定義の動作が発生します。

第2に、画像の同期URLダウンロードのように見えます。ディスク上のファイルURLからロードする場合は、私を修正してください。同期イメージのダウンロードは、UIを正しくブロックしていたため、これを別のスレッドに移動したのはおそらく理由でしょうか?メインスレッドで同期APIを使用しないようにネットワークにアクセスする方法について最初に知っておくべきことの1つです。非同期ダウンロードを行うには、NSURLConnectionクラスを検討しましたか?

第3に、イメージのダウンロードがセルの表示に直接リンクされないように、これを再設計する必要があります。

表のセルを表示するには、残りのUIでメインスレッドを実行する必要があります。セルが表示されたら、画像を非同期にダウンロードするための呼び出しを行う必要があります。イメージのダウンロードが完了したら、イメージのダウンロードをキャッシュし、デリゲートコールバックを介してセルに通知する必要があります。その後、画像が表示されます。

NSOperationにこれらの種類をラップし、NSOperationQueueを使用して管理できます。これらのクラスのドキュメントを参照して、それらの使用方法を学ぶためのサンプルコードをチェックアウトしてください。

関連する問題