2016-05-24 21 views
2

私は4回api呼び出しを行います。それらは次の順序である必要があります:バックグラウンドで同期してAPI呼び出しを行うには?

apiSyncDataToCloud;

apiSyncImagesToServer;

apiDeleteDataFromCloud;

apiSyncDataFromCloudInBackground;

前者が正常終了するか失敗するかにかかわらず、それぞれが呼び出されます。

また、それぞれに成功と失敗の完了ブロックがあります。

成功するとブロックデータベースが更新されます。

すべてこのプロセスは、背景で実行する必要があるとのノーを行わなければを持っています。Apiの呼び出しはもちろんバックグラウンドで実行されますが、呼び出しが完了するとデータベースの更新がメインスレッドで実行され、アプリがフリーズします。

しようとしました次のコード:

だから、私はいくつかのソリューションと一緒に行った

NSOperationQueue *queue = [NSOperationQueue new]; 

queue.maxConcurrentOperationCount = 1; 


[queue addOperationWithBlock:^{ 
    [self apiSyncDataToCloud]; 
}]; 

[queue addOperationWithBlock:^{ 
    [self apiSyncImages]; 
}]; 

[queue addOperationWithBlock:^{ 
    [self apiDeleteDataFromCloud]; 
}]; 

[queue addOperationWithBlock:^{ 
    [self apiSyncDataFromCloudInBackground]; 
}]; 

をしかし、これは唯一のAPIメソッドの呼び出しが順序で実行されることを保証します。しかし、その結果は具体的な命令には従いません。つまり、メソッド呼び出しは指定された順序になりますが、apiSyncImagesToServerのsuccessブロックは、apiSyncDataToCloudの成功ブロックの前に呼び出される可能性があります。

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
    [self apiSyncDataToCloud]; 
}); 

と私はapiSyncImagesToServerと呼ばれているapiSyncDataToCloudの成功と失敗のブロックで:

は、それから私は、以下の溶液を用いて行きました。これもあまり働かなかった。

私は最後の解決策をとっていきます。私はapiSyncDataToCloudを呼び出しています。

成功すれば、このメソッドはデータベースを更新してから、他のAPIを呼び出します。

失敗完了ブロックでは、このメソッドは単純にデータベースを更新せずにapi呼び出しを行います。次のようにapiSyncDataToCloudの例 -

構造については

は次のとおりです。

-(void)apiSyncDataToCloud{ 

NSLog(@"method 1"); 

NSMutableDictionary *dicDataToBeSynced = [NSMutableDictionary dictionary]; 
dicDataToBeSynced = [self getDataToBeSynced]; 

if (dicDataToBeSynced.count!=0) { 
    if ([[StaticHelper sharedObject] isInternetConnected]) { 

     [[ApiHandler sharedObject] postRequestWithJsonString:API_SYNC_DATA_TO_CLOUD andHeader:[UserDefaults objectForKey:kAuthToken] forHeaderField:kAccessToken andParameters:dicDataToBeSynced WithSuccessBlock:^(NSURLResponse *response, id resultObject, NSError *error) { 

      NSLog(@"Data synced successfully to server"); 
      [self updateColumnZSYNC_FLAGForAllTables];//updating db 
      [self apiSyncImagesToServer];//api call 


     } andFailureBlock:^(NSURLResponse *task, id resultObject, NSError *error) { 
      NSLog(@"Data syncing to cloud FAILED"); 
      [self apiSyncImagesToServer];//simply make api call without updating db 

     }]; 
    } 
}else{ 
    [self apiSyncImagesToServer];make api call even if no data to be synced found 

} 

}

Similaryは、apiSyncImagesToServerの内側に私はその結果apiDeleteDataFromCloud .....

を呼び出しています私の問題はそのまま残っていました。それは、dbを更新する成功ブロック、画像のダウンロード、すべての操作がメインスレッドで実行されるときにフリーズします。

Plzもっと清潔で優れたソリューションを教えてください。

答えて

2

カスタムキューとコール要求を1つずつ作成することができます。 すなわち

dispatch_queue_t myQueue;//declare own queue 

if (!myQueue) {//check if queue not exists 
     myQueue = dispatch_queue_create("com.queue1", NULL); //create queue 
} 
dispatch_async(myQueue, ^{[self YOUR_METHOD_NAME];});//call your method in queue block 

あなたは、メインスレッド上でUIを更新し、データを受信した後、いくつかのUIを更新したい場合。

1

1)この種の状況では、AFNetworkingを使用する方が良い。 AFNetworkingがメインの&バックグラウンドスレッドを処理する優れた方法を提供するためです。 AFNetworkingは成功と失敗のブロックをサポートしているため、前回のWS Apiコールの成功と失敗から1つずつWS Apiコールを実行できます。したがって、この期間中に進捗状況HUDが表示されます。最後のAPIが成功し、DBが更新され、進行状況HUDが非表示になります。

2)NSOperationQueue and NSInvocationOperation を使用する必要がある場合は、このリンクをクリックしてください。 https://www.raywenderlich.com/76341/use-nsoperation-nsoperationqueue-swift

+0

もちろん、AFNetworkingを使用してこれらのAPIコールを作成しています。成功と失敗のブロックはメインスレッドで実行されます。そして、私は、api呼び出しを行うか、成功と失敗のブロックを実行するか、いくつかのバックグラウンドスレッドで実行されるように、オペレーション全体を必要とします。 – mars

+0

成功または失敗ブロックはメインスレッドで返されます。 – krunal

0

API呼び出しは、バックグラウンドで実行もちろんであるが、呼び出し後 は、データベースの更新がそれによって アプリを凍結メインスレッド上で実行されて完了する。

なぜ別のキューで実行してみませんか? 時間のかかるタスクを実行するために

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
    //your code 
}); 

を使用してみてくださいとだけ更新UIへ

dispatch_async(dispatch_get_main_queue(), ^{ 
    //your code 
}); 

+0

はい私は現在このアプローチに従っています。しかし、私はもっと良い選択肢が来るのを待っている。 – mars

関連する問題