Изменение управляемых объектов в NSArray - PullRequest
0 голосов
/ 20 апреля 2010

У меня есть объект с именем «Job» с двумя логическими атрибутами, который называется «complete» и «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 ]

1 голос
/ 20 апреля 2010

Во-первых, вы можете немного почистить вещи с помощью:

[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, равным нулю и указателем (вашего объявления не было). Если нет, то начальное состояние этого указателя не определено и определенно не равно нулю.
  • Убедитесь, что в выборке нет ошибок.
  • Проверка на счетчик не нужна, так как быстрый перечислитель обработает ее для вас.
  • Сохранение после каждого объекта расточительно, если только у вас нет тысяч объектов, сохраняйте в конце.
  • Пройдите по коду в отладчике и убедитесь, что вы возвращаете объекты и перебираете их.
1 голос
/ 20 апреля 2010

Некоторые примечания, которые могут помочь:

Цикл 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];
}
0 голосов
/ 20 апреля 2010

Я здесь не эксперт, но думаю, что вам нужно сообщить контекст управляемого объекта с помощью setPrimitiveValue: чтобы внести изменения Так что попробуйте.

[self willChangeValueForKey:@"logged"];
[self setPrimitiveValue:[NSNumber numberWithBool:YES] forKey:@"logged"];
[self didChangeValueForKey:@"logged"];
0 голосов
/ 20 апреля 2010

Что, если вы используете метод KVC (Key Value Coding):

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

Есть ли у вас метод setLogged в вашем пользовательском классе NSManagedObject?

...