在多线程环境中对谓词的不可预测的结果

时间:2016-11-23 07:07:41

标签: ios multithreading core-data objective-c-blocks nspredicate

我们正在开发一个应用程序来收集信标信息并将新的/更新的数据同步到服务器。我们使用核心数据来收集信标信息,但偶尔我们发现核心数据框架在同步到服务器时会产生错误的结果。有时谓词在第一次迭代后失败,同时从核心数据中获取数据以进行同步。因此,我们正在寻求有关长期使用核心数据和持久存储数据库所遇到的任何问题的建议。

我正在使用以下步骤将核心数据记录逐个同步到服务器

-(void)syncDataToServer{
if( !isSycInProgress ){


    //predicate fetch records which newly created and which are synced to server yet
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"isSynced == %@",[NSNumber numberWithBool:NO]];
    //fetch only one record at one time to utilize memory
   NSArray *beaconRecordArray = [[ISCoreDataManager sharedManager] fetchObjectList:@"BeaconRecords" predicate:predicate attributeName:@"endTime" batchSize:1 offset:0 isAscending:YES inContext:mainContext];
    BeaconRecords *beacon = nil;
    if(beaconRecordArray.count){
        isSycInProgress = YES;
        beacon = [beaconRecordArray firstObject];
            {
                //create request parameter dictionary
                NSDictionary *dict = @{
                                       @"uid": [beacon.uID description],
                                       @"title":beacon.title.length?beacon.title:@"No title",
                                       @"url": beacon.urlString?beacon.urlString:@"",
                                       };
                //call webservice to upload records on server
               __block NSManagedObjectID *objId = beacon.objectID;
                [[WebServiceHelper sharedInstance] callPostDataWithMethod:beconUrlPostAddBecon withParameters:dict withHud:YES  success:^(NSDictionary *response)
                 {
                     if([response isKindOfClass:[NSDictionary class]] && [response[@"status"] intValue] == 200){
                         NSString *responseStr =response[@"response_crypt_data"];
                         NSError *error;
                         //Decrypt data to fetch parameters in response
                         NSData *decryptedData = [RNDecryptor decryptData:[[NSData alloc] initWithBase64EncodedString:responseStr options:0] withPassword:secretKey error:&error];
                         DLog(@"decrypted data %@", [[NSString alloc] initWithData:decryptedData encoding:NSUTF8StringEncoding]);
                         //parse data
                         //convert data into collection format (for parsing)
                         NSError *parseJsonError = nil;
                         NSDictionary *decryptedResponse = [NSJSONSerialization JSONObjectWithData:decryptedData options:NSJSONReadingMutableContainers error:&parseJsonError];
                         //store Server id in local db for future reference to update record
                             BeaconRecords *beaconRec = [self.privateContext existingObjectWithID:objId error:nil];
                             [self.privateContext performBlock:^{
                                 if(!error && !parseJsonError){
                                     beaconRec.serverID = [NSString stringWithFormat:@"%@",decryptedResponse[@"id"]];
                                     beaconRec.isSynced = @(YES);
                                     [[ISCoreDataManager sharedManager] dbSaveInContext:self.privateContext];
                                 }
                                 //update isSynced flag in local db
                                 isSycInProgressBeaconRecords = NO;
                                 dispatch_async( dispatch_get_main_queue(), ^{
                                     [self  syncDataToServer]; // call this method recursively to upload all records which are pending to sync
                                 });
                            }];
                     }
                     else
                     {
                        isSycInProgress = NO;
                         dispatch_async(dispatch_get_main_queue(), ^{
                             [self  syncDataToServer]; // call this method recursively to upload all records which are pending to sync
                         });
                     }
                 } errorBlock:^(id error) {
                     isSycInProgress = NO;
                       dispatch_async(dispatch_get_main_queue(), ^{
                             [self syncDataToServer]; // call this method recursively to upload all records which are pending to sync
                         });
                 }];
            }
        return;
    }
    isSycInProgress = NO;
    } 
}

成功将第一条记录同步到服务器后,当我以递归方式调用同一个同步函数来上传第二条记录时,该谓词给了我之前上传过的相同记录。奇怪的是isBynched属性的fetched属性是(是),我的谓词说它应该是(_NO)。

0 个答案:

没有答案