我遇到了一个问题,每次我在RestKit 0.20.2中执行映射操作时,我都会重复写入SQLite数据库。我已经非常广泛地在网上查看,似乎找不到我所遇到的重复问题 - 我所看到的所有类似问题都围绕着使用RestKit进行一切,而我正在使用RestKit进行映射和数据库操作,因为我正在另一个库中进行网络方面。
我有一个唯一的identificationAttribute
属性集(推文ID)并使用managedObjectCache
初始化RKInMemoryManagedObjectCache
;但是,每次执行映射操作时,我都会在所有内容上全面重复。我用于网络端的库(STTwitter)将JSON作为数组返回,因此我遍历数组中的每个对象。我应该执行一些其他操作吗?我的印象是,在进行任何插入之前,RestKit会将映射对象中指定的identificationAttribute
属性与SQLite数据库中已有的属性进行比较。当我使用RKManagedObjectRequestOperation
将其用于另一个项目中的所有内容时,我没有遇到此问题。
以下是我设置模型的方法:
-(void)setup
{
self.objectStore = [[RKManagedObjectStore alloc] initWithManagedObjectModel:[self managedObjectModel]];
[self.objectStore createPersistentStoreCoordinator];
NSString *path = [RKApplicationDataDirectory() stringByAppendingPathComponent:@"FoodTruckxxx.sqlite"];
NSLog(@"Setting up store at %@", path);
[self.objectStore addSQLitePersistentStoreAtPath:path
fromSeedDatabaseAtPath:nil
withConfiguration:nil
options:self.optionsForSQLiteStore
error:nil];
[self.objectStore createManagedObjectContexts];
self.objectStore.managedObjectCache = [[RKInMemoryManagedObjectCache alloc] initWithManagedObjectContext:self.objectStore.persistentStoreManagedObjectContext];
}
以下是我执行映射操作的方法:
-(void)performMapping
{
int i = 0;
while (i < self.localCopyOfAllStatuses.count)
{
RKManagedObjectStore *store = [[FoodTruckDataModel sharedDataModel] objectStore];
RKEntityMapping *mapping = [ObjectMappings FoodTruckArticleMapping];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"FoodTruck" inManagedObjectContext:store.persistentStoreManagedObjectContext];
NSManagedObject *newManagedObject = [[NSManagedObject alloc] initWithEntity:entity insertIntoManagedObjectContext:store.persistentStoreManagedObjectContext];
RKManagedObjectMappingOperationDataSource *mappingDS = [[RKManagedObjectMappingOperationDataSource alloc] initWithManagedObjectContext:store.persistentStoreManagedObjectContext cache:store.managedObjectCache];
//assign new array to contain to just one object at a time and iterate through it
NSArray *justOneStatus = [self.localCopyOfAllStatuses objectAtIndex:i];
RKMappingOperation *operation = [[RKMappingOperation alloc] initWithSourceObject:justOneStatus destinationObject:newManagedObject mapping:mapping];
operation.dataSource = mappingDS;
NSError *error = nil;
[operation performMapping:&error];
[store.persistentStoreManagedObjectContext save:&error];
[store.persistentStoreManagedObjectContext saveToPersistentStore:&error];
i++;
}
}
这是映射:
+(RKEntityMapping *)FoodTruckArticleMapping
{
RKEntityMapping *jsonMapping = [RKEntityMapping mappingForEntityForName:@"FoodTruck" inManagedObjectStore:[[FoodTruckDataModel sharedDataModel] objectStore]];
jsonMapping.identificationAttributes = @[@"tweetID"];
[jsonMapping addAttributeMappingsFromDictionary:@{
@"text": @"tweet", @"user.screen_name": @"foodTruckName", @"created_at": @"timeStamp", @"id": @"tweetID"}];
return jsonMapping;
}
here是我日志中的完整操作。任何帮助将不胜感激!
答案 0 :(得分:2)
根据这个问题的答案on the RestKit Google Group board(我验证了有效),解决方法是不在我的NSManagedObject
中创建nil
并将destinationObject
分配给RKMappingOperation
{1}}声明。下面是这个方法的正确代码,以及我最初问题的答案:
-(void)performMapping
{
int i = 0;
while (i < self.localCopyOfAllStatuses.count)
{
RKManagedObjectStore *store = [[FoodTruckDataModel sharedDataModel] objectStore];
RKEntityMapping *mapping = [ObjectMappings FoodTruckArticleMapping];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"FoodTruck" inManagedObjectContext:store.persistentStoreManagedObjectContext];
RKManagedObjectMappingOperationDataSource *mappingDS = [[RKManagedObjectMappingOperationDataSource alloc] initWithManagedObjectContext:store.persistentStoreManagedObjectContext cache:store.managedObjectCache];
//assign new array to contain to just one object at a time and iterate through it
NSArray *justOneStatus = [self.localCopyOfAllStatuses objectAtIndex:i];
RKMappingOperation *operation = [[RKMappingOperation alloc] initWithSourceObject:justOneStatus destinationObject:nil mapping:mapping];
operation.dataSource = mappingDS;
NSError *error = nil;
[operation performMapping:&error];
[store.persistentStoreManagedObjectContext save:&error];
[store.persistentStoreManagedObjectContext saveToPersistentStore:&error];
i++;
}
}
但是,RestKit Google Group链接中还建议我实现RKMapperOperation
而不是RKMappingOperation,
,因为它可以省去迭代我的JSON响应数组的麻烦。这就是我最终使用的内容,为了提高效率和更好地使用RestKit,我提出了这些内容:
-(void)performMapping
{
RKManagedObjectStore *store = [[FoodTruckDataModel sharedDataModel] objectStore];
RKManagedObjectMappingOperationDataSource *mappingDS = [[RKManagedObjectMappingOperationDataSource alloc] initWithManagedObjectContext:store.persistentStoreManagedObjectContext cache:store.managedObjectCache];
RKMapperOperation *mapperOperation = [[RKMapperOperation alloc] initWithRepresentation:self.localCopyOfAllStatuses mappingsDictionary:@{ [NSNull null]: [ObjectMappings FoodTruckArticleMapping] }];
mapperOperation.mappingOperationDataSource = mappingDS;
NSError *error = nil;
[mapperOperation execute:&error];
[store.persistentStoreManagedObjectContext save:&error];
[store.persistentStoreManagedObjectContext saveToPersistentStore:&error];
}
答案 1 :(得分:0)
目前,您在循环中显式创建托管对象实例,因此RestKit没有机会检查重复项。相反,您应该为RestKit提供整个JSON响应,并让它完成所有映射和对象创建。
要实现此目的,请查看使用RKManagedObjectResponseMapperOperation
。此操作允许您指定托管对象上下文,映射和整个响应内容(您不明确地执行任何循环)。这为RestKit提供了检查重复项所需的所有信息。
有些事情:
RKManagedObjectResponseMapperOperation *responseMapperOperation = [[RKManagedObjectResponseMapperOperation alloc] initWithRequest:self.request
response:self.response
data:self.responseData
responseDescriptors:self.responseDescriptors];
responseMapperOperation.mapperDelegate = self;
responseMapperOperation.managedObjectContext = self.managedObjectContext;
responseMapperOperation.managedObjectCache = self.managedObjectCache;
[responseMapperOperation setDidFinishMappingBlock:^(RKMappingResult *mappingResult, NSError *responseMappingError) {
// use the mappingResult which contains the received objects
}];
将responseMapperOperation添加到要执行的队列中。
请务必导入所需的RestKit类。