在NSArray中更改ManagedObjects

时间:2010-04-20 08:50:41

标签: iphone objective-c core-data nsarray

我有一个名为'Job'的实体,有两个名为'completed'和'logged'的布尔属性。 我正在尝试检索所有尚未在应用启动时记录的已完成作业,并将其更改为已记录。我可以使用此fetchRequest获取所有已完成但未记录的作业:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(completed == %@ && logged == %@)", [NSNumber numberWithBool:YES], [NSNumber numberWithBool:NO]];

然后我将此谓词分配给fetchRequest并调用[managedObjectContext executeFetchRequest:fetchRequest]方法以获取满足此条件的所有Job实体的数组。这似乎工作正常,并返回正确数量的工作。

我一直在尝试做的是循环返回NSArray,将logged属性设置为YES然后保存。这似乎已完成,并且不会返回任何错误,但在应用程序退出时不会保留更改。我哪里错了?

[fetchRequest setPredicate:predicate];
NSError error;
NSArray jobsToLog = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
if ([jobsToLog count] > 0) {
   for (int i = 0; i < [jobsToLog count] - 1; i++) {
      [[jobsToLog objectAtIndex:i] setLogged:[NSNumber numberWithBool:YES]];
      // Commit the changes made to disk
      error = nil;
      if (![managedObjectContext save:&error]) {
         // An error occurred
      }
   }
}

感谢您的期待,

4 个答案:

答案 0 :(得分:1)

可能会有所帮助的一些注意事项:

for循环从0循环到小于计数的1。这将跳过上一份工作。如果只有一份工作,那么什么都不会发生。将循环更改为:

for (int i = 0; i < [jobsToLog count]; i++)

for (int i = 0; i <= [jobsToLog count] - 1; i++)

当从NSArray中提取对象时,编译器将不知道其类型。您应该显式地转换对象:

  [(Job *)[jobsToLog objectAtIndex:i] setLogged:[NSNumber numberWithBool:YES]];

您可以使用快速枚举执行以上两种操作:

for(Job *thisJob in jobsToLog) {
  [thisJob setLogged:[NSNumber numberWithBool:YES];
}

答案 1 :(得分:1)

首先,你可以通过以下方式清理一下:

[fetchRequest setPredicate:predicate];
NSError *error = nil;
NSArray jobsToLog = [managedObjectContext executeFetchRequest:fetchRequest error:&error];
NSAssert1(error == nil, @"Error retrieving jobs: %@", [error userInfo]);
for (id job in jobsToLog) {
  [job setValue:[NSNumber numberWithBool:YES] forKey:@"logged"];
}
if (![managedObjectContext save:&error]) {
  NSAssert1(NO, @"Failed to save %@", [error userInfo]);
}
  • 请注意,我从error开始是nil并且是一个指针(你的声明不是)。如果不这样做,那么该指针的初始状态是未定义的,绝对不是nil。
  • 检查以确保提取中没有错误。
  • 不需要对计数进行检查,因为快速枚举器会为您处理。
  • 在每个对象之后保存是浪费的,除非你有数千个对象,最后保存。
  • 在调试器中遍历您的代码,确保您获取对象并循环遍历它们。

答案 2 :(得分:0)

如果您使用KVC(键值编码)方法怎么办:

[[jobsToLog objectAtIndex:i] setValue:[NSNumber numberWithBool:YES] forKey:@"logged"];

您的自定义NSManagedObject类中是否有setLogged方法?

答案 3 :(得分:0)

我不是这里的专家,但我认为您需要使用setPrimitiveValue来告知托管对象上下文:进行更改。试试吧。

[self willChangeValueForKey:@"logged"];
[self setPrimitiveValue:[NSNumber numberWithBool:YES] forKey:@"logged"];
[self didChangeValueForKey:@"logged"];