以编程方式将新记录添加到Cocoa Core数据实体

Mar*_*ino 0 macos cocoa core-data objective-c cocoa-bindings

我正在Cocoa中创建一个简单的基于文档的应用程序.此应用程序的每个文档基本上应该管理日期和注释的数组,因此每个记录都是日期和注释(textview).每个文档也受密码保护.

为此,我创建了一个名为HistoryElement的Core Data实体(包含日期和notes属性),我还创建了一个Settings实体,该实体应该只包含一个包含打开文件密码的记录(我没有找到更好的方法,有一个?密码绑定到每个文件,所以我不能使用首选项,因为它不是一个全局应用程序密码).

我有一个首选项选项卡,其中包含一个密码文本字段,该文本字段绑定到Settings实体的密码属性.

好的...现在的问题是:当我创建一个新文档时,Settings实体上没有记录,所以我希望以编程方式添加一个,这样用户就可以放入(如果要保护它的文件)密码密码文本字段.

相反,如果我打开现有文件,它应该发现已经添加了Settings实体的记录,并且它不应该再创建它,而是密码文本字段应该使用这个.

我尝试了很多方法,但我无法做到这一点.我试过这个例子:

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

    NSLog(@"Init settings");`

    [settingsArrayController add:self];`

} 
Run Code Online (Sandbox Code Playgroud)

它似乎在我创建新文档时添加了一条新记录,但如果我在密码文本字段中输入密码然后保存文档,当我再次打开文档时[[settingsArrayController arrangedObjects] count]返回0并再次创建新记录...

我怎样才能做到这一点 ?有一个更好/简单/优雅的方式来保护密码的文件?

Cay*_*den 5

在初始化managedObjectContext并加载数据后,您需要将代码添加到NSPersistentDocument.很难说你发布的示例代码有什么问题而不知道你把它放在哪里.

你可以放在一个简单的地方是在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.
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,我在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];
}
Run Code Online (Sandbox Code Playgroud)

这应该就是它的全部内容.

我创建了一个快速示例项目,说明了您需要执行的操作:http://dl.dropbox.com/u/21359504/coredata-example.zip