以编程方式向 Cocoa 核心数据实体添加新记录

发布于 2024-10-16 18:26:37 字数 862 浏览 8 评论 0原文

我正在 Cocoa 中制作一个简单的基于文档的应用程序。该应用程序的每个文档基本上应该管理一组日期和注释,因此每个记录都是一个日期和一个注释(文本视图)。此外,每个文档均受密码保护。

为此,我创建了一个名为 HistoryElement 的核心数据实体(包含日期和注释属性),我还创建了一个设置实体,该实体应该只有一条记录,其中包含打开文件的密码(我没有找到更好的方法,有一个?密码与每个文件相关联,因此我无法使用首选项,因为它不是全局应用程序密码)。

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

好吧...现在的问题是这样的:当我创建一个新文档时,“设置”实体上没有记录,因此我希望以编程方式添加一个记录,以便用户可以将密码(如果想保护其文件)放入密码文本字段。

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

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

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

    NSLog(@"Init settings");`

    [settingsArrayController add:self];`

} 

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

我该怎么做?有更好/简单/优雅的方法来使用密码保护文档吗?

i'm making a simple document-based application in Cocoa. Each document of this app should basically manage an array of Dates and Notes, so each record is a date and a note (textview). Also each document is protected by password.

To do that i created a Core Data entity called HistoryElement (that contains a date and a notes attribute), i also created a Settings entity that should have only a record which contains the password to open the file (i didn't found a better method, there is one ? The password is tied to each file, so i can't use preferences because it's not a global application password).

I have a preference tab which contain a Password textfield that binds to the password attribute of the Settings entity.

Ok...the problem is now this: when i create a new document there are no records on the Settings entity, so i wish to programmatically add one, so the user can put (if it want to protect it's file) the password in the password text field.

Instead, if i'm opening an existing file it should find that a record for Settings entity has been already add and it shouldn't create it again, instead the password text field should use this one.

I tried many ways, but i'm unable to do that. I tried for example this:

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

    NSLog(@"Init settings");`

    [settingsArrayController add:self];`

} 

It seems that it adds a new record when i create a new document, but if i put a password in the password text field and then save the document, when i open the document again the [[settingsArrayController arrangedObjects] count] returns 0 and it creates a new record again...

How can i do that ? There is a better/simple/elegant way to protect a document with a password ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

笨死的猪 2024-10-23 18:26:37

在初始化 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.
    }
}

请注意,我在 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

You need to add the code to NSPersistentDocument after the managedObjectContext has been initialized and the data has been loaded. It's hard to say what's wrong with the sample code you posted without knowing where you put it.

One easy place you could put it is in the windowControllerDidLoadNib. For example,

- (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.
    }
}

Note that I am using a category on NSManagedObjectContext that does all the boiler plate query stuff:

// 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];
}

And that should be all there is to it.

I have created a quick sample project that illustrates what you need to do at: http://dl.dropbox.com/u/21359504/coredata-example.zip

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文