【问题标题】:Core Data optimistic locking errorCore Data 乐观锁定错误
【发布时间】:2017-06-14 17:04:18
【问题描述】:

我正在从将 JSON 数组传递回我的应用程序的 Web 服务中获取大量数据,我正在使用两个不同的 Web 服务,一个用于每个核心数据实体来加载数据,但我遇到了乐观锁定错误来自核心数据。

不是每个实体都进行核心数据锁定吗?所以我可以同时将对象插入两个不同的实体?

我的代码如下所示

网络服务 1

+(void)fetchPricelistAll:(int)pricelistId :(int)startAtRow :(int)takeNoOfRows;
{
    if ([NWTillHelper isDebug] == 1) {
        NSLog(@"WebServices:fetchPriceList:priceListId = %d", pricelistId);
    }

    if([[NWTillHelper getUserName]  isEqual: @"matt"]) {
        takeNoOfRows = 100;
    }

    NSString *finalURL = [NSString stringWithFormat:@"https://host.domain.com:5443/api/till/tillpricelistv2/%d?StartAtRow=%d&TakeNoOfRows=%d",pricelistId, startAtRow, takeNoOfRows];

    [[[NSURLSession sharedSession] dataTaskWithURL:[NSURL URLWithString:finalURL]
                                 completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {

                                     if (error != nil) {
                                         if ([NWTillHelper isDebug] == 1) {
                                             NSLog(@"WebServices:fetchPriceList:Transport error %@", error);
                                         }
                                     } else {
                                         NSHTTPURLResponse *responseHTTP;
                                         responseHTTP = (NSHTTPURLResponse *) response;

                                         if(responseHTTP.statusCode != 200) {
                                             if ([NWTillHelper isDebug] == 1) {
                                                 NSLog(@"WebServices:fetchPriceList:Server Error %d", (int) responseHTTP.statusCode);
                                             }
                                         } else {
                                             NSArray *priceListObjectArray = [NSJSONSerialization JSONObjectWithData:data
                                                                                                             options:0
                                                                                                               error:NULL];
                                             if ([NWTillHelper isDebug] == 1) {
                                                 NSLog(@"WebServices:fetchPriceList:count = %lu", (unsigned long)[priceListObjectArray count]);
                                                 NSLog(@"WebServices:fetchPriceList:PricelistObjectArray looks like %@",priceListObjectArray);
                                             }

                                             NSDictionary *priceListObjectDict;

                                             //Loop through the array and for each dictionary insert into local DB
                                             for (id element in priceListObjectArray){
                                                 priceListObjectDict = element;

                                                 NSString *currencyName = [priceListObjectDict objectForKey:@"currencyName"];
                                                 NSString *price = [priceListObjectDict objectForKey:@"price"];
                                                 NSString *priceIncTax = [priceListObjectDict objectForKey:@"priceIncTAX"];
                                                 NSString *validFrom = [priceListObjectDict objectForKey:@"validFromDate"];
                                                 NSString *validTo = [priceListObjectDict objectForKey:@"validToDate"];
                                                 NSString *itemId = [priceListObjectDict objectForKey:@"itemID"];

                                                 NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
                                                 [dateFormat setDateFormat:@"YYYY-MM-dd'T'HH:mm:ss"];
                                                 NSDate *validToDate = [dateFormat dateFromString:validTo];
                                                 NSDate *validFromDate = [dateFormat dateFromString:validFrom];

                                                 if([NWTillHelper isDebug] == 1) {
                                                     NSLog(@"WebServices:fetchPriceList:validToDate: >>>> %@ <<<<", validToDate);
                                                     NSLog(@"WebServices:fetchPriceList:validFromDate: >>>> %@ <<<<", validFromDate);
                                                 }

                                                 // Use Core Data FMD
                                                 AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication]delegate];

                                                 NSManagedObjectContext *context =
                                                 appDelegate.persistentContainer.viewContext;
                                                 context.mergePolicy = NSMergeByPropertyStoreTrumpMergePolicy;

                                                 if([NWTillHelper isDebug] == 1) {
                                                     NSLog(@"PimItemListView:tableView:context = %@", context);
                                                 }

                                                 NSManagedObject *newPrlItem = Nil;
                                                 newPrlItem = [NSEntityDescription
                                                               insertNewObjectForEntityForName:@"PriceList"
                                                               inManagedObjectContext:context];

                                                 [newPrlItem setValue:itemId forKey:@"itemId"];
                                                 [newPrlItem setValue:validToDate forKey:@"validTo"];
                                                 [newPrlItem setValue:validFromDate forKey:@"validFrom"];
                                                 [newPrlItem setValue:price forKey:@"price"];
                                                 [newPrlItem setValue:priceIncTax forKey:@"priceIncTax"];
                                                 [newPrlItem setValue:currencyName forKey:@"currencyName"];

                                                 NSError *error = Nil;
                                                 [context save:&error];

                                                 if ([NWTillHelper isDebug] == 1) {
                                                     NSLog(@"WebServices:fetchTillData:ItemId in loop = %@", itemId);
                                                     NSLog(@"WebServices:fetchTillData:newPrlItem = %@", newPrlItem);
                                                     NSLog(@"WebServices:fetchTillData:CoreData error = %@", error);
                                                 }

                                                 if(error != nil) {
                                                     // TODO: Useful error message to user
                                                 } else {
                                                     NSUserDefaults *tillUserDefaults = [NSUserDefaults standardUserDefaults];
                                                     [tillUserDefaults setInteger:1 forKey:@"hasPriceList"];
                                                     [tillUserDefaults synchronize];
                                                 }

                                             }
                                         }
                                     }
                                 }] resume];
}

网络服务 2

+ (void)fetchTillDataAll:(int)tillId :(int)startAtRow :(int)takeNoOfRows {

    if([[NWTillHelper getUserName]  isEqual: @"matt"]) {
        takeNoOfRows = 100;
    }

    if ([NWTillHelper isDebug] == 1) {
        NSLog(@"WebServices:fetchTillDataAll:tillId = %d, startAtRow = %d, takeNoOfRows = %d", tillId, startAtRow, takeNoOfRows);
    }

    NSString *finalURL = [NSString stringWithFormat:@"https://host.domain.com:5443/api/till/tilldatav2/%d?StartAtRow=%d&TakeNoOfRows=%d",tillId, startAtRow, takeNoOfRows];

    [[[NSURLSession sharedSession] dataTaskWithURL:[NSURL URLWithString:finalURL]
                                 completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {

                                     if (error != nil) {
                                         if ([NWTillHelper isDebug] == 1) {
                                             NSLog(@"WebServices:fetchTillDataAll:Transport error %@", error);
                                         }
                                     } else {
                                         NSHTTPURLResponse *responseHTTP;
                                         responseHTTP = (NSHTTPURLResponse *) response;

                                         if(responseHTTP.statusCode != 200) {
                                             if ([NWTillHelper isDebug] == 1) {
                                                 NSLog(@"WebServices:fetchTillDataAll:Server Error %d", (int) responseHTTP.statusCode);
                                             }
                                         } else {
                                             NSArray *tillBasicDataArray = [NSJSONSerialization JSONObjectWithData:data
                                                                                                           options:0
                                                                                                             error:NULL];
                                             if ([NWTillHelper isDebug] == 1) {
                                                 NSLog(@"WebServices:fetchTillDataAll:tillBasicDataArray count = %lu", (unsigned long)[tillBasicDataArray count]);
                                                 NSLog(@"WebServices:fetchTillDataAll:tillBasicDataArray looks like %@",tillBasicDataArray);
                                             }

                                             NSDictionary *tillBasicDataDict = Nil;

                                             //Loop through the array and for each dictionary insert into local DB
                                             for (id element in tillBasicDataArray){
                                                 tillBasicDataDict = element;

                                                 NSString *itemId = [tillBasicDataDict objectForKey:@"itemId"];
                                                 NSString *brandId = [tillBasicDataDict objectForKey:@"companyId"];
                                                 NSString *languageId = [tillBasicDataDict objectForKey:@"languageCode"];
                                                 NSString *colorCode = [NSString stringWithFormat:@"%@", [tillBasicDataDict objectForKey:@"colorCode"]];
                                                 NSString *discountable = [tillBasicDataDict objectForKey:@"discountable"];
                                                 NSString *exchangeable = [tillBasicDataDict objectForKey:@"exchangeable"];
                                                 NSString *noos14 = [tillBasicDataDict objectForKey:@"noos14"];
                                                 NSString *sizeCode = [NSString stringWithFormat:@"%@", [tillBasicDataDict objectForKey:@"sizeCode"]];
                                                 NSString *taxGroup = [tillBasicDataDict objectForKey:@"taxGroupId"];
                                                 NSString *taxRegion = [tillBasicDataDict objectForKey:@"taxRegion"];
                                                 NSString *tradeItemDesc = [tillBasicDataDict objectForKey:@"tradeItemDesc"];
                                                 NSString *withTax = [tillBasicDataDict objectForKey:@"withTax"];
                                                 NSString *status = [tillBasicDataDict objectForKey:@"status"];

                                                 // Use Core Data FMD
                                                 AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication]delegate];

                                                 NSManagedObjectContext *context =
                                                 appDelegate.persistentContainer.viewContext;
                                                 context.mergePolicy = NSMergeByPropertyStoreTrumpMergePolicy;

                                                 NSManagedObject *newPimItem = Nil;
                                                 newPimItem = [NSEntityDescription
                                                               insertNewObjectForEntityForName:@"TillData"
                                                               inManagedObjectContext:context];

                                                 [newPimItem setValue:itemId forKey:@"itemId"];
                                                 [newPimItem setValue:brandId forKey:@"brandId"];
                                                 [newPimItem setValue:languageId forKey:@"languageCode"];
                                                 [newPimItem setValue:colorCode forKey:@"colorCode"];
                                                 [newPimItem setValue:discountable forKey:@"discountable"];
                                                 [newPimItem setValue:exchangeable forKey:@"exchangeable"];
                                                 [newPimItem setValue:noos14 forKey:@"noos14"];
                                                 [newPimItem setValue:sizeCode forKey:@"sizeCode"];
                                                 [newPimItem setValue:[NSNumber numberWithInt:[taxGroup intValue]] forKey:@"taxGroup"];
                                                 [newPimItem setValue:taxRegion forKey:@"taxRegion"];
                                                 [newPimItem setValue:tradeItemDesc forKey:@"tradeItemDesc"];
                                                 [newPimItem setValue:[NSNumber numberWithInt:[withTax intValue]] forKey:@"withTax"];
                                                 [newPimItem setValue:[NSNumber numberWithInt:[status intValue]] forKey:@"status"];

                                                 NSError *error = Nil;
                                                 [context save:&error];

                                                 if ([NWTillHelper isDebug] == 1) {
                                                     NSLog(@"WebServices:fetchTillDataAll:ItemId in loop = %@", itemId);
                                                     NSLog(@"WebServices:fetchTillDataAll:newPimItem = %@", newPimItem);
                                                     NSLog(@"WebServices:fetchTillDataAll:CoreData error = %@", error);
                                                 }

                                                 if(error != nil) {
                                                     // Do something here
                                                 } else {
                                                     NSUserDefaults *tillUserDefaults = [NSUserDefaults standardUserDefaults];
                                                     [tillUserDefaults setInteger:1 forKey:@"hasTillData"];
                                                     [tillUserDefaults synchronize];
                                                 }
                                             }
                                         }
                                     }
                                 }] resume];
}

为什么这会导致乐观锁定错误消息?

【问题讨论】:

  • 托管上下文使用了什么并发类型?
  • NSManagedObjectContext *context = appDelegate.persistentContainer.viewContext; context.mergePolicy = NSMergeByPropertyStoreTrumpMergePolicy;
  • 如何指定并发类型?
  • 检查这个developer.apple.com/documentation/coredata/…。我还看到您使用 viewContext 并从 WebService 保存数据,我建议为每个服务使用私有上下文。
  • 我查看了文档,我正在尝试在持久化容器中实现后台任务,会告诉你进展如何

标签: objective-c core-data


【解决方案1】:

问题在于托管上下文。当您使用viewContext 属性时,您必须在主线程上执行所有操作。

当您在不同线程(不是主线程)上执行长时间操作时,最好使用newBackgroundContext() 方法为此操作创建新的托管上下文。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-04-27
    • 2019-07-20
    • 2017-10-02
    • 1970-01-01
    • 2014-03-07
    • 2010-09-12
    • 2011-05-21
    相关资源
    最近更新 更多