Restkit 核心数据与 NSManagedObjectContext 集成

Posted

技术标签:

【中文标题】Restkit 核心数据与 NSManagedObjectContext 集成【英文标题】:Restkit Core data integration with NSManagedObjectContext 【发布时间】:2012-04-19 18:55:26 【问题描述】:

在过去的几周里,我正在学习 Restkit (v0.10.0) 和核心数据,使用这些出色的工具可以提供无穷无尽的可能性。问题是我对如何在这里看到更大的图景有点不知所措。而且由于 Restkit 的更新速度非常快,大多数教程/演示代码已经过时,不再正常工作。

我已经设法让我的 tableview 充满了远程服务器上我的 json 中的数据。我还研究了如何使远程数据与缓存相结合现在工作,但我正在努力解决 NSManagedObjectContext/NSEntityDescription(核心数据)以及在使用 POST 命令时它如何与 Restkit 一起工作。

如果我理解正确,记录是在 Core Data 中创建的(在注释行 // Create a new instance 之后),然后该数据用于创建 POST 请求,以便将记录发布到服务器。

此代码用于在服务器上创建新记录,但是当代码执行时(我看到在我的服务器上创建了一条记录),但我的 tableview 没有相应更新,table view 没有更新,因此重新启动应用程序时,新记录首先可见。从服务器手动刷新数据也无济于事。

希望有人可以给我一些指导,或者可能是一个包含 Restkit/核心数据和 POST 组合的教程。谢谢!

- (void)createGoalWithName:(NSString *)name andDescription:(NSString *)goalDescription

    Goal* goal = [Goal object];
    goal.identifier = 0;
    goal.name = name;
    goal.goalDescription = goalDescription;

    // Create a new instance of the entity managed by the fetched results controller.
    NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext];
    NSEntityDescription *entity = [[self.fetchedResultsController fetchRequest] entity];
    [NSEntityDescription insertNewObjectForEntityForName:[entity name] inManagedObjectContext:context];

    [self saveContext];

    [[RKObjectManager sharedManager].router routeClass:[Goal class] toResourcePath:@"/api/goals" forMethod:RKRequestMethodPOST];

    [[RKObjectManager sharedManager] postObject:goal delegate:self];

    [self.tableView reloadData];


- (void)saveContext 
    NSManagedObjectContext *context = [self.fetchedResultsController managedObjectContext];
    NSError *error = nil;
    if (![context save:&error]) 
    /*
     Replace this implementation with code to handle the error appropriately.

     abort() causes the application to generate a crash log and terminate. 

     You should not use this function in a shipping application, 
     although it may be useful during development. 

     If it is not possible to recover from the error, 
     display an alert panel that instructs the user to quit the application by pressing the Home button.
     */
    NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
    abort();

【问题讨论】:

我一直在研究同样类型的事情。 Here是RestKit和Core data教程的链接。 是的,我也看过那个教程。问题是它已经很老了,而且 RestKit 的大部分工作方式都随着时间的推移而发生了变化。不过谢谢! 如果您想得到答案,我认为您需要详细说明如何填充UITableView。上面的代码显示了(可能)有效的持久性机制,但您没有解释如何尝试检索此数据以显示在表中。 :-) 我试过使用RestKit,也遇到了同样的问题。经过一周的彻底沮丧后,我放弃了并打包了自己的服务,该服务功能较少,但更易于使用。如果您有兴趣尝试一下,希望得到反馈。 github.com/loudin/RSAPI 我现在正在尝试您的解决方案 Michael D。谢谢! 【参考方案1】:

使用RestKit+CoreData时必须使用blocks,忘记路由器设置:

NSString *postUrl = @"/someurl/newelement";    
[ [RKObjectManager sharedManager] loadObjectsAtResourcePath:postUrl usingBlock:^(RKObjectLoader* loader) 
    loader.serializationMIMEType = RKMIMETypeJSON;

    loader.delegate = nil;
    loader.targetObject = nil;
    loader.method= RKRequestMethodPOST; // change to GET, POST, PUT etc
];

【讨论】:

【参考方案2】:

由于您不包含 UI 代码,因此很难完全诊断此问题,但是当您重新启动应用程序时显示更新可能会发生一件事,即您没有正确同步两者之间的更改各种线程的本地托管对象上下文。 RestKit 有自己的托管对象上下文,因为它不在主 UI 线程上运行。

在这个 Apple 文档中介绍了在 Core Data 中使用多个线程的概念:http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/CoreData/Articles/cdConcurrency.html,但要点是您需要注册通知 NSManagedObjectContextDidSaveNotification,然后在 UI 线程上调用 mergeChangesFromContextDidSaveNotification:托管对象上下文以安全地合并在 RestKit 线程上完成的更改。

请记住,通知将发布在 RestKit 线程上,因此您可能必须在主 UI 线程上运行更新,例如在接收通知的方法中是这样的:

[self.managedObjectContextForMainThread performSelectorOnMainThread:@selector(mergeChangesFromContextDidSaveNotification:) withObject:notification waitUntilDone:YES];

NSManagedObjectContext* managedObjectContextForMainThread 属性已正确初始化以指向 UI 线程的托管对象上下文。

希望这会有所帮助(如果您还没有完全放弃 RestKit...)

【讨论】:

【参考方案3】:

我仍在使用稍旧版本的 Restkit。但一个关键要素是必须定义主键属性。 这样 Restkit 就可以让你的本地存储对象和服务器对象保持同步。

在您的情况下,为您的目标对象定义映射时,您会这样做: 目标映射.primaryKeyAttribute = @"标识符";

【讨论】:

Tjeerd,感谢您的回复,但这不是问题所在。我的代码中有这个语句,但在其他地方。

以上是关于Restkit 核心数据与 NSManagedObjectContext 集成的主要内容,如果未能解决你的问题,请参考以下文章

Restkit 核心数据与 NSManagedObjectContext 集成

删除请求并将 RESTkit 与核心数据和线程同步

restkit:映射 to_many 与核心数据的关系

RestKit:如何删除核心数据条目以保持内容与服务器同步?

RestKit 与特定核心数据对象的关系连接,无需键映射

Restkit核心数据明细数据