RestKit + CoreData:只有在远程保存成功后才能在本地保存对象?

时间:2012-06-09 01:09:38

标签: ios core-data restkit

我在iOS 5.0部署目标上使用带有Core Data的RestKit 0.10.1来构建与自定义RESTFul API接口的应用程序。由于离线连接很重要,因此我在设备的本地CoreData数据库中维护用户数据的缓存。

现在,RestKit非常棒,设置RKFetchResultsTableController以轻松显示和保存我的数据已经相当轻松了。但是,RestKit有一种行为似乎并不理想,我无法弄清楚如何改变。

我有一个名为'录音'的模型。要创建新录制,我将执行以下操作:

 Recording *r = [NSEntityDescription insertNewObjectForEntityForName:@"Recording" inManagedObjectContext:[[RKObjectManager sharedManager].objectStore managedObjectContextForCurrentThread]];

 r.name = newName; 

[[RKObjectManager sharedManager] sendObject:r toResourcePath:@"/recordings" usingBlock:^(RKObjectLoader *loader){
        loader.delegate = self; 
        loader.method = RKRequestMethodPOST;
        loader.serializationMIMEType = RKMIMETypeJSON;  

        loader.serializationMapping = [RKObjectMapping serializationMappingUsingBlock:^(RKObjectMapping *serializationMapping){
            [serializationMapping mapAttributes:@"name", nil];

        }];

        RBMappingProvider *mappings = (RBMappingProvider *)[[RKObjectManager sharedManager] mappingProvider];
        loader.objectMapping = [mappings recordingObjectMapping];

    }];

这会创建一个“Recording”类型的新实体,然后在POST请求中将实体发送到服务器。在成功案例中,这很有效。

然而,问题是服务器有时会合法地拒绝这些创建。我在这些情况下发现的是,核心数据数据库中已存在实体的本地副本,其id为0(id是服务器设置的主键)。

删除本地实体的唯一方法是强制从服务器刷新本地数据。

只有在服务器以2xx响应时,是否有办法在本地持久保存对象?或者,有没有办法撤消更改,如果服务器响应除了2xx之外的任何东西?

谢谢,

1 个答案:

答案 0 :(得分:0)

不幸的是,因为Recording是NSManagedObject,所以甚至需要将临时实例插入到托管对象上下文中。 @Mundi维护引用并在错误之后将其从上下文中删除的解决方案是我将使用的解决方案。一些额外的代码会从服务器上完全刷新。

升级到0.20.x会使这更容易。发送请求时使用的成功和失败块使得保留此引用并在失败时将其删除非常容易。例如:

[_objectManager postObject:aMessage
                      path:@"message"
                parameters:parameters
                   success:^(RKObjectRequestOperation * operation, RKMappingResult * mappingResult){
                     // Success code here
                   }
                   failure:^(RKObjectRequestOperation * operation, NSError * error){
                     [_managedObjectContext deleteObject:aMessage];
                     [_managedObjectContext save:nil];
                   }];