我正在开发的应用程序也支持套接字更新,我正在使用SocketIO来处理. SocketIO也正在完美运行,服务器发出的每个事件我都会收到,除非应用程序当时没有运行.
当我尝试从套接字事件中获取json数据并将其映射到核心数据时,会出现此问题.如果套接字事件同时进入,响应从我通过RKObjectManager发出的请求返回,并且它们都是第一次给我相同的对象,它们通常最终在coredata中制作相同ManagedObject的2个副本,我在控制台中收到以下警告:
托管对象缓存为[modelObjectName]实体配置的标识符返回了2个对象,预期为1.
这是我制作的包含制作RKMapperOperation的代码的方法:
+(void)createOrUpdateObjectWithJSONDictionary:(NSDictionary*)jsonDictionary { RKManagedObjectStore* managedObjectStore = [CMRAManager sharedInstance].objectManager.managedObjectStore; NSManagedObjectContext* context = managedObjectStore.mainQueueManagedObjectContext; [context performBlockAndWait:^{ RKEntityMapping* modelEntityMapping = [self entityMappingInManagedObjectStore:managedObjectStore]; NSDictionary* modelPropertyMappingsByDestinationKeyPath = modelEntityMapping.propertyMappingsByDestinationKeyPath; NSString* modelMappingObjectIdSourceKey = kRUClassOrNil([modelPropertyMappingsByDestinationKeyPath objectForKey:NSStringFromSelector(@selector(object_Id))],RKPropertyMapping).sourceKeyPath; NSString* modelObjectId = [jsonDictionary objectForKey:modelMappingObjectIdSourceKey]; CMRARemoteObject* existingObject = [self searchForObjectOfCurrentClassWithId:modelObjectId]; RKMapperOperation* mapperOperation = [[RKMapperOperation alloc]initWithRepresentation:jsonDictionary mappingsDictionary:@{ [NSNull null]: modelEntityMapping }]; [mapperOperation setTargetObject:existingObject]; RKManagedObjectMappingOperationDataSource* mappingOperationDataSource = [[RKManagedObjectMappingOperationDataSource alloc]initWithManagedObjectContext:context cache:managedObjectStore.managedObjectCache]; [mappingOperationDataSource setOperationQueue:[NSOperationQueue new]]; [mappingOperationDataSource setParentOperation:mapperOperation]; [mappingOperationDataSource.operationQueue setMaxConcurrentOperationCount:1]; [mappingOperationDataSource.operationQueue setName:[NSString stringWithFormat:@"%@ with operation '%@'",NSStringFromSelector(_cmd),mapperOperation]]; [mapperOperation setMappingOperationDataSource:mappingOperationDataSource]; NSError* mapperOperationError = nil; BOOL mapperOperationSuccess = [mapperOperation execute:&mapperOperationError]; NSAssert((mapperOperationError == nil) && (mapperOperationSuccess == TRUE),@"Execute mapperOperation error"); if (mapperOperationError || (mapperOperationSuccess == FALSE)) { NSLog(@"mapperOperationError: %@",mapperOperationError); } NSError* contextSaveError = nil; BOOL contextSaveSuccess = [context saveToPersistentStore:&contextSaveError]; NSAssert((contextSaveError == nil) && (contextSaveSuccess == TRUE),@"Save context error"); }]; }
在上面的代码中,我首先尝试获取现有的托管对象(如果它当前存在)以将其设置为映射器请求的目标对象.查找对象的方法(searchForObjectOfCurrentClassWithId :)如下所示:
+(instancetype)searchForObjectOfCurrentClassWithId:(NSString*)objectId { NSManagedObjectContext* context = [CMRAManager sharedInstance].objectManager.managedObjectStore.mainQueueManagedObjectContext; __block CMRARemoteObject* fetchedObject = nil; [context performBlockAndWait:^{ NSFetchRequest* fetchRequest = [self fetchRequestForCurrentClassObjectWithId:objectId]; NSError* fetchError = nil; NSArray *entries = [context executeFetchRequest:fetchRequest error:&fetchError]; if (fetchError) { NSLog(@"fetchError: %@",fetchError); return; } if (entries.count != 1) { return; } fetchedObject = kRUClassOrNil([entries objectAtIndex:0],CMRARemoteObject); if (fetchedObject == nil) { NSAssert(FALSE,@"Should be of this class"); return; } }]; return fetchedObject; }
我对此问题的最佳猜测是,它可能是由于托管对象上下文及其线程造成的.我对他们应该如何工作没有最好的理解,因为我已经能够依赖于Restkit对它的正确使用.我已经尽力复制Restkit如何设置这些映射操作,但我假设我在上面的代码中出现了错误.
如果它有用,我愿意发布任何其他代码.我没有发布我的RKEntityMapping代码,因为我很确定错误并不存在 – 毕竟,当它执行mapper操作时,Restkit已成功映射这些对象,即使有多余的JSON对象/数据也是如此地图.
我认为问题必须是我对托管对象上下文及其线程执行不良的另一个原因是因为我在iPhone 5c和iPod touch上进行测试,而且iPod touch上没有问题,我认为它只有1个核心,但iPhone 5c确实有时会遇到这个问题,我相信它有多个核心.我应该强调一点,我不确定我在本段中所做的陈述是否一定都是正确的,所以不要以为我知道我在谈论器件内核,这只是我认为我读过的内容之前.
解决方法
NSManagedObjectContext *firstContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; firstContext.parentContext = [RKObjectManager sharedInstance].managedObjectStore.mainQueueManagedObjectContext; firstContext.mergePolicy = NSOverwriteMergePolicy; RKEntityMapping* modelEntityMapping = [self entityMappingInManagedObjectStore:[CMRAManager sharedInstance].objectManager.managedObjectStore]; RKMappingOperation *operation = [[RKMappingOperation alloc] initWithSourceObject:jsonDictionary destinationObject:nil mapping:modelEntityMapping]; // Restkit memory cache sometimes creates duplicates when mapping quickly across threads RKManagedObjectMappingOperationDataSource *mappingDS = [[RKManagedObjectMappingOperationDataSource alloc] initWithManagedObjectContext:firstContext cache:[RKFetchRequestManagedObjectCache new]]; operation.dataSource = mappingDS; NSError *mappingError; [operation performMapping:&mappingError]; [operation waitUntilFinished]; if (mappingError || !operation.destinationObject) { return; // ERROR } [firstContext performBlockAndWait:^{ [firstContext save:nil]; }];
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。