0

Web サービス経由でデータをフェッチし、そのデータを Core Data データストアに保持し、デリゲート メソッド経由で ViewController を更新する DataFetcher というモデル クラスがあります。NSOperation を使用しない場合の通常のシーケンス (正常に動作する) は次のとおりです。

NSArray *serviceQueryResult = [self queryServiceFor:@"car"];
[self setData:serviceQueryResult];
[self persistData:_data];
[_loadDelegate updateCount:_data.count]; 
[_loadDelegate receivedData:_data];

Web サービス呼び出しとデータベース更新呼び出しをバックグラウンド スレッドに配置する必要があります。私の考えでは、NSBlockOperation を作成して Web サービスを呼び出し、次に別の NSBlockOperation を作成してデータベースの更新を行うことです。データベースの更新操作が開始される前に Web サービス操作が完了するという依存関係があります。実装しようとしているコードは次のとおりです。

__weak DataFetcher *weakSelf = self;
__block NSArray *serviceQUeryResult;
NSBlockOperation *webServiceOperation = [NSBlockOperation blockOperationWithBlock:^{
    serviceQUeryResult = [weakSelf queryServiceFor:@"mini"];
    [weakSelf setData:serviceQUeryResult];
}];
NSBlockOperation *dbInsertOperation = [NSBlockOperation blockOperationWithBlock:^{
    [weakSelf persistData:serviceQUeryResult];
}];

[webServiceOperation addDependency:dbInsertOperation];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperation:webServiceOperation];

このように設定すると、 queryServiceFor: メソッドが呼び出されません。2 つのデリゲート メソッド呼び出しは UI を更新し、メイン スレッド上にある必要があるため、どこに配置すればよいかもわかりません。過去に何度か GCD を使用しましたが、NSOperations の追加機能が必要になります。誰でも助けることができますか?ありがとう!

4

1 に答える 1

2

webServiceOperation根本的な問題は、依存していると宣言したdbInsertOperation(つまり、終了するwebServiceOperationまで開始しないdbInsertOperation) ことですが、決して開始dbInsertOperationしないため、webServiceOperation決して実行されません。

  1. dbInsertOperationに依存させたいwebServiceOperation場合は、次のことは望ましくありません。

    [webServiceOperation addDependency:dbInsertOperation];
    

    代わりに次のことが必要です。

    [dbInsertOperation addDependency:webServiceOperation];
    
  2. この依存関係を作成したら、これらの操作の両方をキューに追加してください。

    [queue addOperation:webServiceOperation];
    [queue addOperation:dbInsertOperation];
    

    依存関係により、終了dbInsertOperationするまで起動しないことが保証されwebServiceOperationます。これは、webServiceOperationがそのブロックを同期的に実行することを前提としていることに注意してください。ネットワーク リクエストが非同期で実行される場合は、それを独自の並行/非同期NSOperationサブクラスにラップすることができます。


これらのバックグラウンド操作から UI を更新する場合は、次のいずれかを実行できます。

[[NSOperationQueue mainQueue] addOperationWithBlock:^{
    // update the UI here
}];

または、必要に応じて GCD を使用します。

dispatch_async(dispatch_get_main_queue(), ^{
    // update the UI here
});
于 2014-09-26T16:55:32.193 に答える