2011-01-31 5 views
0

多くの画像を非同期的にダウンロードして(xmlで解析されたリンク)、tableViewのセルに配置する方法を知りたいと思います。私はMarkJのチュートリアルを試しましたが、セルのimageViewに表示させたいという点を除いて、完全に機能しました。あなたがこれを行う方法を私に教えることができれば、それはすばらしいことでしょう。多くの画像を非同期的にダウンロードしてtableViewセルのimageViewに配置する方法

答えて

2

NSOperation(ImageDownloadOperationのようなもの)を拡張し、ダウンロード操作をグローバルNSOperationQueueに追加します。ダウンロードが完了したときにイメージを設定するテーブルビューのセルにコールバックがあります。申し訳ありませんが、大量のカスタムコードがあるため、コード例はありません。これは、JSONオブジェクトから解析されたリンクを使ってこれを行った方法です。

3

私も同様のケースがありますが、私のデータフォーマットはxmlではなくJSONです。ダウンロードと非同期の部分は非常に似ているはずです。 Objective-CブロックとGCDのdispatch_asyncメソッドで試してみることにしました。私のコードの重要な部分は以下の通りですが、不要な部分は除外されています。

イメージと呼ばれるイメージをキャッシュするために使用するNSDictionaryがあります。最初のステップは、現在のNSIndexPathのイメージがあるかどうかを確認することです。もしそうなら、私は単にそのイメージを返すだけです。そうでない場合は、プレースホルダイメージを作成し、実際のイメージのダウンロードを開始し、プレースホルダを返します。

「実際のイメージのダウンロードを開始する」という部分は、使用したいキューがすでに存在するかどうかを確認し、作成していない場合はチェックします。 NSDataの便利メソッドdataWithContentsOfURLにバックグラウンドスレッドで非同期呼び出しを行います。これはブロッキングコールですが、バックグラウンドスレッド上にあるため、UIは応答しています。呼び出しが返ってくると、データからUIImageを作成し、イメージをキャッシュし、indexPathのセルを取得します。次に、単にセル上のimageView.imageプロパティを設定する別のdispatch_async呼び出しを行います。ここで重要な点は、メインスレッドだけがUIを更新する権限を持っているため、dispatch_get_main_queue()を使用してメインスレッドを管理するキューへの参照を取得することです。

RootViewController.h

#import <UIKit/UIKit.h> 

@interface RootViewController : UITableViewController { 

    //An array of dictionary objects 
    NSArray *tweets; 

    //A place to cache images 
    NSDictionary *images; 

    // the dispatch queue to load images 
    dispatch_queue_t queue; 
} 

@property (nonatomic, retain) NSArray *tweets; 
@property (nonatomic, retain) NSDictionary *images; 

@end 

RootViewController.m

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    static NSString *CellIdentifier = @"Cell"; 

    UITableViewCell *cell = ...; 
    //set up the cell 
    .... 
    cell.imageView.image = [self imageForRowAtIndexPath:indexPath]; 
    return cell; 
} 

- (UIImage *)imageForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    // get the dictionary for the indexPath 
    NSDictionary *tweet = ...; 

    // get the user dictionary for the indexPath 
    NSDictionary *user = [tweet objectForKey:@"user"]; 

    // get the user's id and check for a cached image first 
    NSString *userID = [user objectForKey:@"id_str"]; 
    UIImage *image = [self.images objectForKey:userID]; 
    if(!image) 
    { 
     // if we didn't find an image, create a placeholder image and 
     // put it in the "cache". Start the download of the actual image 
     image = [UIImage imageNamed:@"Placeholder.png"]; 
     [self.images setValue:image forKey:userID]; 

     //get the string version of the URL for the image 
     NSString *url = [user objectForKey:@"profile_image_url"]; 

     // create the queue if it doesn't exist 
     if (!queue) { 
      queue = dispatch_queue_create("image_queue", NULL); 
     } 

     //dispatch_async to get the image data 
     dispatch_async(queue, ^{ 

      NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:url]]; 
      UIImage *anImage = [UIImage imageWithData:data]; 
      [self.images setValue:anImage forKey:userID]; 
      UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath]; 

      //dispatch_async on the main queue to update the UI 
      dispatch_async(dispatch_get_main_queue(), ^{ 
       cell.imageView.image = anImage; 
      }); 
     }); 
    } 

    // return the image, it could be the placeholder, or an image from the cache 
    return image; 
} 
+0

私の答えは、それらを使用するよう、タグObjective-Cのブロックを追加する方法はありますか? – Adam

+0

したがって、キューが存在しないことがわかっている場合は、キューを作成しているかのように見えます。あなたがこの小切手を持っていなかったらどうなるでしょう。私は、私の "com.mycompanyname.myproject.imagequeue"に与えていた一意の名前は、dispatch_queue_createが私に実際の "新しい"キューを返さないようにするのに十分だと仮定していましたが、すでに作成したものと同じキューを返します。私はdispatch_queue_createがdispatch_queue_get_or_createのようなものだと仮定していると思います。私の前提は外されていますか? –

+0

正直言って、私のCのfooはかなり上にはない。オブジェクトと構造体の違いは私には完全には分かりません。 dispatch_queue_createから返されるものは構造体です。私は簡単なテスト、https://gist.github.com/1042828を書いています。同じ名前をdispatch_queue_createに渡しても、別の構造体が得られますが、それらは有効でブロックを実行できます。私のチェックの背後にあるアイデアは、キューがまだ作成されていない場合はそのキューを作成し、そのクラスの周りにそのキューを保持してから、dispatch_releaseを使用してdeallocで解放します。 – Adam

関連する問題