在RestKit 0.20.2中创建的重复Core Data对象

时间:2013-06-09 05:10:40

标签: ios core-data restkit

我遇到了一个问题,每次我在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是我日志中的完整操作。任何帮助将不胜感激!

2 个答案:

答案 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类。