如何在后台同步进行api调用?

时间:2016-05-24 06:15:13

标签: ios objective-c

我有四个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的成功块可能在apiSyncDataToCloud成功阻止之前被调用。

然后我选择了以下解决方案:

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

在apiSyncDataToCloud的成功和失败块中,我调用了apiSyncImagesToServer。这也没有用。

现在我只是按照我的最后一个解决方案。我只是在调用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

}

}

同样,在apiSyncImagesToServer里面我正在调用apiDeleteDataFromCloud .....

结果我的问题仍然存在。当成功阻止更新数据库,下载图像时,应用程序会冻结...正在主线程上执行的所有操作。

Plz让我知道更清洁,更好的解决方案。

3 个答案:

答案 0 :(得分:2)

您可以逐个创建自己的自定义队列和呼叫请求。 即。

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)

1)最好在这种情况下使用AFNetworking。因为AFNetworking提供了更好的方式来处理Main&背景线程。 AFNetworking支持成功和失败块,因此您可以通过先前WS Api调用的成功和失败逐个进行WS Api调用。所以在这段时间内显示进度HUD。最后一个API的成功然后更新数据库并隐藏进度HUD。

2)如果你需要使用NSOperationQueue and NSInvocationOperation 并点击此链接。 https://www.raywenderlich.com/76341/use-nsoperation-nsoperationqueue-swift

答案 2 :(得分:0)

  

Api通话当然是在后台执行,但一旦通话   完成数据库更新在主线程上执行从而冻结   应用程序。

那么为什么不在单独的队列中执行呢? 尝试使用

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

执行耗时的任务和

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

仅更新用户界面。