3

我遇到了一个问题,每次在 RestKit 0.20.2 中执行映射操作时,我都会对我的 SQLite 数据库进行重复写入。我在网上进行了相当广泛的研究,似乎找不到与我遇到的问题重复的问题——我看到的所有类似问题都集中在使用 RestKit 处理所有问题,而我只使用 RestKit 进行映射和数据库操作,因为我在另一个库中做网络方面的工作。

我有一个唯一的identificationAttribute属性集(推文 ID),并且正在使用managedObjectCache初始化为RKInMemoryManagedObjectCache; 但是,每次我执行映射操作时,我都会在所有内容上得到全面的重复。我用于网络端的库 (STTwitter) 将 JSON 作为数组返回,因此我遍历数组中的每个对象。还有其他一些我应该执行的操作吗?我的印象是 RestKitidentificationAttribute在进行任何插入之前会将映射对象中指定的属性与 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;
}

这是我日志中的完整操作任何帮助将不胜感激!

4

2 回答 2

2

根据RestKit Google Group board (我验证有效)上对这个问题的回答,解决方案是不创建一个并在我的声明NSManagedObject中分配nil给。以下是此方法的正确代码,以及我最初问题的答案:destinationObjectRKMappingOperation

-(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];
}
于 2013-06-18T04:31:03.420 回答
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 类。

于 2013-06-09T20:55:04.023 回答