10

メールアドレスを含むデータを Web API から取得する iPhone アプリを作成しています。表のセルに各電子メール アドレスに関連付けられた画像を表示したいので、アドレス帳で画像を検索し、電子メール アドレスが本にない場合はデフォルトに戻ります。これはうまく機能しますが、いくつかの懸念があります。

  • パフォーマンス: 電子メール アドレス (または電話番号) でアドレス帳のレコードを検索するために私が見つけたレシピは、かなり遅いと報告されています。この理由は、アドレス帳のすべてのレコードを反復処理し、画像を持つレコードごとに、すべての電子メール アドレスを反復処理して一致を見つける必要があるためです。もちろん、大きなアドレス帳の場合、これには時間がかかります。

  • 表のセル: そこで、画像を検索する必要があるすべての電子メール アドレスを集めて、それらを一度にすべて検索しようと考えました。このようにして、すべてのアドレスに対して本を 1 回だけ反復処理します。しかし、これは、各セルが 1 つの電子メール アドレスに対応する表のセルではうまく機能しません。セルを表示する前にすべての画像を収集する必要があります (遅くなる可能性があります)。または、各セルが読み込まれるときに各画像を検索する必要があります (それぞれの一致を見つけるために本を反復処理する必要があるため、さらに遅くなります)。メールアドレス)。

  • 非同期ルックアップ:それで、NSInvocationOperation. AddressBook で見つかった各画像のサムネイルをアプリのサンドボックスに保存します。次に、各セルはこのファイルを参照し、存在しない場合はデフォルトを表示できます (ブックにないか、まだ見つかっていないため)。画像が後で非同期ルックアップで見つかった場合、次に画像を表示する必要があるときに突然表示されます。これは、イメージを定期的に再生成する場合 (たとえば、アドレス帳でイメージが変更された場合) に適しています。しかし、私のアプリの特定のインスタンスでは、画像が実際にはしばらく表示されない場合があります。

  • 非同期テーブル セル ルックアップ: 理想的には、markjnet の非同期テーブル セル更新のようなものを使用して、ダウンロードされた画像でテーブル セルを更新します。NSInvocationOperationしかし、これが機能するためには、セルが表示され、キャッシュされたアイコンがサンドボックスにない場合に、セルごとにジョブをスピンオフする必要があります。しかしその後、アドレス帳全体を 1 つずつ非効率的に反復処理することに戻ります。大量の新しい電子メール アドレスをダウンロードしただけの場合は、大量のアドレスになる可能性があります。

だから私の質問は:他の人はこれをどのように行うのですか?私は Tweetie2 をいじっていましたが、表示された表のセルを非同期的に更新しているようです。必要な画像ごとに個別のHTTPリクエストを送信していると思います。もしそうなら、電子メール アドレスでローカル アドレス帳を検索することはそれほど効率的ではないと思うので、おそらくそれが最善の方法でしょうか? アドレス帳の検索に関連するパフォーマンスの問題について心配する必要はありませんか?

もしそうなら、サムネイル画像をサンドボックスに保存するのがキャッシングの最善の方法ですか? また、アドレス帳の変更に合わせてすべてのサムネイルを 1 日 1 回更新する新しいジョブを作成したい場合、どのように行うのが最善の方法でしょうか?

残りの皆さんは、この種の問題をどのように解決しますか? 提案をいただければ幸いです。

4

4 に答える 4

2

画像の実際のキャッシュにどの戦略を使用するかに関係なく、可能であれば、電子メールアドレスのバッチを取得するたびにアドレスブックデータを1回だけパスします。(はい、これは非同期で行います。)

検索結果のメモリ内キャッシュとして機能するNSMutableDictionaryを作成します。ダウンロードからの各電子メールアドレスをキーとして、センチネルをそのキーの値(など[NSNull null])として、この辞書を初期化します。

次に、アドレス帳の各ABRecordRefを反復処理し、ABRecordCopyValue(record, kABPersonEmailProperty)返される各ABMultiValueの結果を呼び出してループします。メールアドレスのいずれかがキャッシュ内のキーで[NSNumber numberWithInt:ABRecordGetRecordId(record)]ある場合は、辞書でそのキーの値として設定します。

この辞書をルックアップインデックスとして使用すると、フープジョーンズの回答で示唆されているように、ユーザーの現在のスクロール位置を指定して、テーブルビューに現在表示している電子メールアドレスのみのABRecordRefsの画像をすばやく取得できます。アプリケーションでそのレベルの「最新性」が必要な場合は、アドレス帳変更リスナーを追加してキャッシュを無効にし、別のインデックス作成操作をトリガーしてから、ビューを更新できます。

于 2010-02-15T15:22:13.090 に答える
2

リストした最後の方法(非同期テーブルセルルックアップ)を使用しますが、表示されている現在のレコードの画像のみを検索します。UIScrollViewDelegateメソッドをオーバーロードして、ユーザーがスクロールを停止したことを確認し、現在表示されているセルの要求のみを開始します。

このようなもの(これは私が今見つけることができないウェブ上で見つけたチュートリアルからわずかに変更されています、著者を引用しなかったことをお詫びします):

- (void)loadContentForVisibleCells
{
    NSArray *cells = [self.table visibleCells];
    [cells retain];
    for (int i = 0; i < [cells count]; i++) 
    { 
        // Go through each cell in the array and call its loadContent method if it responds to it.
        AddressRecordTableCell *addressTableCell = (AddressRecordTableCell *)[[cells objectAtIndex: i] retain];
        [addressTableCell loadImage];
        [addressTableCell release];
        addressTableCell = nil;
    }
    [cells release];
}


- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView; 
{
    // Method is called when the decelerating comes to a stop.
    // Pass visible cells to the cell loading function. If possible change 
    // scrollView to a pointer to your table cell to avoid compiler warnings
    [self loadContentForVisibleCells]; 
}


- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate;
{
    if (!decelerate) 
    {
       [self loadContentForVisibleCells]; 
    }
}

現在表示されているアドレスレコードがわかったら、それら(おそらく5〜7レコード)を検索するだけで非常に高速になります。画像を取得したら、辞書にキャッシュするだけで、後で画像のリクエストをやり直す必要がなくなります。

于 2010-02-14T16:12:51.780 に答える
1

UITableViewにレイジー画像の読み込みを実装しようとしているようです。Appleからの良い例があります、私はここでそれを参照しています: UITableViewでの遅延ロード画像

于 2010-02-14T20:14:53.597 に答える
0

参考までに、画像の非同期読み込みと高速ファイル キャッシュを行うための無料で強力で簡単なライブラリをリリースしました: HJ Managed Objects http://www.markj.net/asynchronous-loading-caching-images-iphone-hjobjman/

于 2011-01-13T17:40:55.200 に答える