Добавление новой записи программно в основной объект данных Какао - PullRequest
0 голосов
/ 10 февраля 2011

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

Для этого я создал сущность Core Data с именем HistoryElement (которая содержит дату и атрибут заметок), а также создал сущность Settings, в которой должна быть только запись, содержащая пароль для открытия файла (я этого не делал нашел лучший метод, есть один? Пароль привязан к каждому файлу, поэтому я не могу использовать настройки, потому что это не глобальный пароль приложения).

У меня есть вкладка настроек, которая содержит текстовое поле «Пароль», которое привязывается к атрибуту пароля объекта «Настройки».

Хорошо ... проблема теперь в следующем: когда я создаю новый документ, в сущности «Настройки» нет записей, поэтому я хочу программно добавить один, чтобы пользователь мог поместить его (если он хочет защитить свой файл) пароль в текстовом поле пароля.

Вместо этого, если я открываю существующий файл, он должен обнаружить, что запись для сущности Настройки уже добавлена, и не должен создавать ее снова, вместо этого в текстовом поле пароля должно использоваться это.

Я пробовал много способов, но я не могу этого сделать. Я пробовал например это:

if([[settingsArrayController arrangedObjects] count] == 0) {`

    NSLog(@"Init settings");`

    [settingsArrayController add:self];`

} 

Кажется, что он добавляет новую запись, когда я создаю новый документ, но если я введу пароль в текстовое поле пароля и затем сохраню документ, когда я снова открою документ, [[settingsArrayController arrangedObjects] count] вернет 0 и он снова создает новую запись ...

Как я могу это сделать? Есть лучший / простой / элегантный способ защитить документ паролем?

1 Ответ

5 голосов
/ 17 февраля 2011

Вам нужно добавить код в NSPersistentDocument после того, как managedObjectContext был инициализирован и данные были загружены. Трудно сказать, что не так с примером кода, который вы разместили, не зная, куда вы его поместили.

Одно простое место, куда вы могли бы поместить это, в windowControllerDidLoadNib. Например,

- (void)windowControllerDidLoadNib:(NSWindowController *)windowController 
{
    [super windowControllerDidLoadNib:windowController];
    // user interface preparation code
    NSManagedObjectContext *moc = [self managedObjectContext];
    NSSet *settings = [moc fetchObjectsForEntityName:@"Settings"
                                     withPredicate:nil];
    if ([settings count] == 0)
    {
      NSManagedObject *obj = [NSEntityDescription insertNewObjectForEntityForName:@"Settings"
                                                           inManagedObjectContext:moc];
      [obj setValue:@"myPass" forKey:@"password"];
    } else {
      // password record already exists, do something else.
    }
}

Обратите внимание, что я использую категорию в NSManagedObjectContext, которая выполняет всю работу с запросами котельной пластины:

// Convenience method to fetch the array of objects for a given Entity
// name in the context, optionally limiting by a predicate or by a predicate
// made from a format NSString and variable arguments.
//
- (NSSet *)fetchObjectsForEntityName:(NSString *)newEntityName
                       withPredicate:(id)stringOrPredicate, ...
{
  NSEntityDescription *entity = [NSEntityDescription
                                 entityForName:newEntityName inManagedObjectContext:self];

  NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
  [request setEntity:entity];

  if (stringOrPredicate)
  {
    NSPredicate *predicate;
    if ([stringOrPredicate isKindOfClass:[NSString class]])
    {
      va_list variadicArguments;
      va_start(variadicArguments, stringOrPredicate);
      predicate = [NSPredicate predicateWithFormat:stringOrPredicate
                                         arguments:variadicArguments];
      va_end(variadicArguments);
    }
    else
    {
      NSAssert2([stringOrPredicate isKindOfClass:[NSPredicate class]],
                @"Second parameter passed to %s is of unexpected class %@",
                sel_getName(_cmd), [stringOrPredicate className]);
      predicate = (NSPredicate *)stringOrPredicate;
    }
    [request setPredicate:predicate];
  }

  NSError *error = nil;
  NSArray *results = [self executeFetchRequest:request error:&error];
  if (error != nil)
  {
    [NSException raise:NSGenericException format:@"%@",[error description]];
  }

  return [NSSet setWithArray:results];
}

И это все, что нужно.

Я создал быстрый пример проекта, который иллюстрирует, что вам нужно сделать по адресу: http://dl.dropbox.com/u/21359504/coredata-example.zip

...