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 应用程序?