1

皆さん!アプリに共有キャッシュを実装しています。バックグラウンドで Web からキャッシュされたデータを取得し、新しく取得したデータでキャッシュと UI を更新するという考え方です。メインスレッドは継続的にキャッシュを使用するため、もちろんスレッドセーフを確保することが秘訣です。他の誰かが使用している可能性がある間は、キャッシュを変更したくありません。

@synchronized を使用して共有リソースへのアクセスをロックすることは、カーネルにトラップされてかなり遅くなるため、ObjectiveC で最も洗練されたアプローチではないことを理解しています。代わりにGCDを使用することは優れた代替手段であると読み続けています(今のところ、そのいとこであるNSOperationは無視しましょう)。私の状況に適したパターンは何かを理解したいと思います. サンプルコードは次のとおりです。

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

// download the data in a background thread
dispatch_async(queue, ^{
    CacheData *data = [Downloader getLatestData];

    // use the downloaded data in the main thread
    dispatch_sync(dispatch_get_main_queue(), ^{
        [AppCache updateCache:data];
        [[NSNotificationCenter defaultCenter] postNotificationName:@"CacheUpdated" object:nil];
    });
});
  1. これは実際に私が考えていることを行うでしょうか?もしそうなら、これは今日この種の状況を処理する最もクリーンなアプローチですか? 私が話していることにかなり近いブログ投稿がありますが、あなたにも再確認したいと思いました.
  2. 同じスレッド/キュー (私の場合はメイン) の共有リソースにのみアクセスし、メインの UI のみを更新する限り、スレッドセーフを効果的に達成できると考えています。あれは正しいですか?

ありがとう!

4

2 に答える 2

1

100 人の開発者にこれを行う最もエレガントな方法を尋ねると、少なくとも 100 の異なる回答が得られます (おそらくそれ以上!)

私がしていること、そして私にとってうまくいっていることは、イメージ管理を行うシングルトン クラスを用意することです。私は Core Data を使用し、サムネイルをストアに直接保存しますが、「大きな」ファイルにはファイル システムと Core Data の URL を使用します。Core Data は、新しいブロック ベースのインターフェイスを使用するように設定されているため、それ自体が管理するプライベート スレッドですべての作業を実行できます。

可能な画像 URL は、メイン スレッドのタグに登録されます。他のクラスは、そのタグの画像を要求できます。画像がそこにない場合は nil が返されますが、このクラスは fetchingFlag を設定し、NSURLConnection に結合された並行 NSOperation を使用して画像をフェッチします。そのメッセージを取得するメソッドは、'[moc performBlock:...]' (待機なし) を使用して処理します。

画像が最終的にリポジトリに追加されると、moc は受信した画像タグを使用してメイン キューに通知を送信します。画像が必要なクラスはこれをリッスンでき、(メインスレッドで) それを取得すると、モックに画像を再度要求できます。これは明らかにそこにあります。

于 2012-09-28T13:44:43.580 に答える
1

はい。その他の考慮事項はさておき、読み取り/書き込み作業をメイン スレッドにシャントする代わりに、プライベート ディスパッチ キューの使用を検討してください。

dispatch_queue_t readwritequeue;
readwritequeue = dispatch_queue_create("com.myApp.cacheAccessQueue", NULL);

次に、AppCache クラスを更新します。

- (void)updateCache:(id)data {
 dispatch_sync(readwritequeue, ^{ ... code to set data ... });
}

- (id)fetchData:... {
 __block id data = nil;
 dispatch_sync(readwritequeue, ^{ data = ... code to fetch data ...});
 return data;
}

次に、元のコードを更新します。

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

// download the data in a background thread
dispatch_async(queue, ^{
    CacheData *data = [Downloader getLatestData];
    **[AppCache updateCache:data];**

    // use the downloaded data in the main thread
    dispatch_async(dispatch_get_main_queue(), ^{
        [[NSNotificationCenter defaultCenter] postNotificationName:@"CacheUpdated" object:nil];
    });
});
于 2012-09-28T14:15:03.167 に答える