【问题标题】:Save CoreData-entities in NSUserDefaults在 NSUserDefaults 中保存 CoreData 实体
【发布时间】:2010-10-04 17:38:03
【问题描述】:

想象一个 CoreData 实体(例如,名为 searchEngine)。
NSManagedObjectContext 管理该实体的一些“实例”。
最终用户将能够使用NSPopupButton 选择他的"standard searchEngine"
NSPopupButton 的selected object 应该绑定到 NSUserDefaults。
问题:

1)@try{保存}

a) 如果您尝试将选定的“实例”直接保存到 NSUserDefaults,则会出现如下内容:

-[NSUserDefaults setObject:forKey:]: 尝试插入非属性值' (entity: searchEngine; id: 0x156f60 ; data: {
    url = "http://google.de/";
    一些属性 = 1;
    名称=“谷歌”;
})' 类 'searchEngine'。

b) 如果您尝试将“实例”转换为 NSData,则会出现以下情况:

-[searchEngine encodeWithCoder:]:无法识别的选择器发送到实例 0x1a25b0

那么知道如何在与 plist 兼容的数据中获取这些实体吗?

2)@try{registerDefaults}

通常registerDefaults:方法在+ (void)initialize中实现。这里的问题是在CoreData从他的数据库加载保存的实体之前调用了这个方法。所以我不能将默认值设置为不存在的对象,对吧?

我知道,很长的问题...但是:try{[me provide:details]} ;D

【问题讨论】:

    标签: cocoa core-data save nsuserdefaults


    【解决方案1】:

    如果您需要存储对特定托管对象的引用,请使用其托管对象 ID 的 URI 表示:

    NSURL *moIDURL = [[myManagedObject objectID] URIRepresentation];
    

    然后您可以将 URL 保存为用户默认值。

    要检索托管对象,请使用:

    NSManagedObjectID *moID = [myPersistentStoreCoordinator managedObjectIDForURIRepresentation:moIDURL];
    NSManagedObject *myManagedObject = [myContext objectWithID:moID];
    

    唯一需要注意的是,您必须确保原始托管对象 ID 是永久的 - 如果您已经保存了对象,这不是问题,或者您可以使用 obtainPermanentIDsForObjects:error:

    【讨论】:

    • 我认为这是一个很好的解决方案。一个小的补充,正如 NSUserDefaults 的文档所说,您需要将 NSURL 对象归档为 NSData。所以要小心不要按原样保存 NSURL。当我试图检索对象时,我只是犯了这个错误并且一直为零。还要注意 NSUserDefaults 有一个 setURL:forKey: 方法。不过,我认为目前这不适用于 iPhone OS。
    • setURL:forKey: 适用于 iOS 4.0 及更高版本
    • 注意! tilish 的评论很重要,正确的解决方案在这里:stackoverflow.com/a/516735/1780492 没有这个你会得到错误信息:“attempt to insert non-property list object x-coredata:”
    【解决方案2】:

    这是目前使用 4.0 中添加的 setURL 和 getURL 方法来避免额外调用 NSKeyedUnarchiver 和 NSKeyedArchiver 的最简洁和最短的方法:

    二传手:

     + (void)storeSomeObjectId:(NSManagedObjectID *)objectId
     {
         [[NSUserDefaults standardUserDefaults] setURL:[objectId URIRepresentation] 
                                                forKey:@"someObjectIdKey"];
         [[NSUserDefaults standardUserDefaults] synchronize];
     }
    

    吸气剂:

     + (SomeManagedObject *)getObjectByStoredId
     {
         NSURL *uri = [[NSUserDefaults standardUserDefaults] URLForKey:@"someObjectIdKey"];
         NSManagedObjectID *objectId = [self.persistentStoreCoordinator managedObjectIDForURIRepresentation:uri];
         SomeManagedObject *object = [self.managedObjectContext objectWithID:objectId];
     }
    

    【讨论】:

      【解决方案3】:

      您不会想尝试归档核心数据实体并存储它。相反,您将存储密钥或其他一些已知属性,并在应用程序启动时使用它来获取实体。

      一些示例代码(根据Core Data Programming Guide 中发布的示例稍作修改):

      NSManagedObjectContext *moc = [self managedObjectContext];
      NSEntityDescription *entityDescription = [NSEntityDescription
          entityForName:@"SearchEngine" inManagedObjectContext:moc];
      NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
      [request setEntity:entityDescription];
      
      NSPredicate *predicate = [NSPredicate predicateWithFormat:
          @"engineName LIKE[c] '%@'", selectedEngineName];
      [request setPredicate:predicate];
      
      NSError *error = nil;
      NSArray *array = [moc executeFetchRequest:request error:&error];
      if (array == nil)
      {
          // Deal with error...
      }
      

      这样您可以将名称保存在用户默认值中,并在必要时获取实体。

      【讨论】:

      • 嗯。你知道为什么array != nil[array count] < 0 ...它不想工作...
      • 如果 array != nil 则没有错误但也可能没有返回记录 ([array count] == 0)... 但是,[array count] 永远不会发生,因为计数消息返回 NSUInteger 类型。编译器很可能会剥离任何此类测试([array count]
      • 是的。我的意思是([数组计数] == 0)。对此感到抱歉。我只是想表达这个数组中没有任何内容。 ;)
      【解决方案4】:

      我的模型将记录的 UUID 保存到 UserDefaults,以便在下次应用启动时启动最后打开的记录。

      public class Patient: NSManagedObject {    
          override public func awakeFromInsert() {
              super.awakeFromInsert()
              uuid = UUID()
      }
      
      extension Patient {
          @NSManaged public var uuid: UUID
          @NSManaged ...
      }
      

      使用唯一 ID (UUID) 标识每条记录是一种很好的做法。您可以将 UUID 保存为字符串,只需调用 uuid.uuidString

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-10-11
        • 2015-02-26
        • 2011-10-02
        • 1970-01-01
        • 1970-01-01
        • 2012-03-26
        相关资源
        最近更新 更多