iPhone 如何使用 Core Data 修改 Persistent store 中包含的数据

Posted

技术标签:

【中文标题】iPhone 如何使用 Core Data 修改 Persistent store 中包含的数据【英文标题】:iPhone How to modify the data contained on the Persistent store using Core Data 【发布时间】:2010-02-27 19:45:44 【问题描述】:

我一直在试图弄清楚如何修改持久存储中包含的数据。 我正在使用UITabBarController 编写具有多个视图的应用程序,我的核心数据方法主要位于主应用程序委托上,但我只会使用来自UItableViewController 视图的这些数据。

为了使用UITableViewController 在主应用程序委托中创建的managedObjectContext,我在viewDidLoad: 方法上使用了以下内容:

MessageAppDelegate *appDelegate = (MessageAppDelegate *)[[UIApplication sharedApplication] delegate];
managedObjectContext = [appDelegate managedObjectContext];

然后应用程序在表格中显示一些消息,当用户选择UITableViewCell (didSelectRowAtIndexPath) 时,我获取消息对象的 ID 并调用以下方法:

[self readMessage:pk];
-(void)readMessage:(NSInteger)pk   
// First I select the data
NSFetchRequest *request = [[NSFetchRequest alloc] init];
// had to setReturnsObjectsAsFaults to NO so I could access the message data
[request setReturnsObjectsAsFaults:NO];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Message" inManagedObjectContext:self.managedObjectContext];
[request setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"pk == %d", pk];
[request setPredicate:predicate];

NSError *error;
NSArray *items = [self.managedObjectContext executeFetchRequest:request error:&error];
[request release];

// Then I update the object
for (Message *thisMessage in items) 
    //I display the message to the console before updating to check the value
    DLog(@"before reading message %@", thisMessage);
    // we set the message flat to YES
    [thisMessage setRead:YES];
    // we set some sample text here (just for testing)
    [thisMessage setMessageText:@"New message text"];
    // I then display the message to the console checking that the flag and text has been updated
    DLog(@"read message %@", thisMessage);


// Finally I save the updated message calling the function posted below
[self saveMOC];


- (void)saveMOC 
 NSError *error;
 if (![managedObjectContext save:&error]) 
  NSLog(@"there was an error saving the message!");
 

之后数据得到正确更新,如果我在保存后从 managedObjectContext 获取数据,我会得到正确的值。 我通过在readMessage 方法的末尾添加以下代码来验证这一点:

    request = [[NSFetchRequest alloc] init];
//required to avoid presenting objects as faults!!
[request setReturnsObjectsAsFaults:NO];
entity = [NSEntityDescription entityForName:@"Message" inManagedObjectContext:[self managedObjectContext]];
[request setEntity:entity];


//Set the sort descriptor
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"pk" ascending:NO];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[request setSortDescriptors:sortDescriptors];
[sortDescriptors release];
[sortDescriptor release];

//Execute the request
NSMutableArray *mutableFetchResults = [[self.managedObjectContext executeFetchRequest:request error:&error] mutableCopy];
if (mutableFetchResults == nil) 
    // Handle the error later
    DLog(@"ERROR: Unable to fetch the results");


[self setMessagesArray:mutableFetchResults];
    NSLog(@"Data now is: %@", mutableFetchResults);
[mutableFetchResults release];
[request release];

问题是,如果我退出应用程序并再次启动它,我的所有消息都会丢失读取属性(或我所做的任何其他更改),并且 tableview 会加载数据,因为它首先保存到持久存储中。

【问题讨论】:

"我将"读取消息属性"设置为 TRUE ..." 这是您没有发布的一个代码块,但可能是最相关的。这段代码被调用了吗?您如何验证属性是否正在更新? 嗨 Joshua,我已经澄清了以上内容。谢谢!! 已解决:我在设置值之前错过了以下代码:[thisMessage willChangeValueForKey:@"read"]; [thisMessage setRead:YES]; [thisMessage didChangeValueForKey:@"read"]; 【参考方案1】:

试试这个,看看对象的变化是否真的被保存了

- (void)saveMOC 
 NSError *error;
 if (![managedObjectContext save:&error]) 
  NSLog(@"there was an error saving the message!");
  else 
  NSLog(@"The message was saved!");
 

因此,对于每次成功的 saveMOC 调用,您应该会看到一条控制台消息。如果正在调用它并且您正在看到消息,那么您一定不能更改“阅读消息”属性。您可以通过在使用断点或使用 NSLog 消息来打印其值之前和之后检查“读取消息”属性的值来检查这一点

【讨论】:

嗨,正是我一直在做的 ;-) 我已经用更多代码更新了这个问题,在 readMessage 方法上我打印了前后的消息,我可以看到它更新得很好但是我一定错过了别的东西。谢谢! 最初是如何填充数据存储的? 我使用另一种方法 addMessage,它所做的只是在 managedObjectContext 中创建一个新的消息对象,然后设置消息的变量(ID、文本、读取标志、发送日期),最后我使用saveMOC 方法来保存它。 (重启应用后任何新消息加载正常)奇怪的是我最初用SQLITE函数编写了这个应用程序但无法更新数据,所以这次使用核心数据重新编写,不知道是否有设置允许 SQLITE 更新或类似的东西。 所以我假设如果您在创建对象时执行[thisMessage setRead:YES];,则在打开应用程序时加载数据时它会显示为已读,对吧? 正确,如果我创建标志设置为 YES 的对象,它显示很好,我也忘了在上面提到删除消息对象工作正常,只更新它们对我不起作用跨度> 【参考方案2】:

-readMessage: 方法是否定义在您的应用委托或视图控制器中?我的猜测是,您在不同的托管对象上下文中更改对象的属性,而不是您尝试保存更改的对象(应用程序委托中的 MOC),这实际上并不知道某些事情发生了变化。另一方面,保留您的更改的 MOC 永远不会保存(更改仅保留在内存中),并且在您重新启动应用程序后,您的更改会丢失。

会是这种情况吗?

【讨论】:

以上是关于iPhone 如何使用 Core Data 修改 Persistent store 中包含的数据的主要内容,如果未能解决你的问题,请参考以下文章

iPhone 4 iOS 5 如何使用 Core Data 保存 MPMediaItem?

iPhone如何使用NSPredicate按父实体过滤Core Data?

如何在 Mac 和 iPhone 之间同步 Core-Data 应用程序?

Core Data iphone调试指针

iPhone 上是不是存在 Core Data?或者您将如何在 iPhone 上保存数据?

如何在 iPhone 应用程序之间共享一个 Core Data 模型?