在NSUserDefaults中保存CoreData实体

时间:2009-02-01 00:35:31

标签: cocoa core-data save nsuserdefaults

想象一下CoreData实体(例如名为searchEngineNSManagedObjectContext管理此实体的某些“实例” 最终用户可以选择"standard searchEngine" NSPopupButton。{。} NSPopupButton的selected object应绑定到NSUserDefaults 问题:

  

1) @try {save}

     
    

a)如果您尝试将选定的“实例”直接保存到NSUserDefaults,可能会出现以下情况:

-[NSUserDefaults setObject:forKey:]: Attempt to insert non-property value ' (entity: searchEngine; id: 0x156f60  ; data: {
    url = "http://google.de/";
    someAttribute = 1;
    name = "google";
})' of class 'searchEngine'.

         

b)如果您尝试将“实例”转换为NSData,请执行以下操作:

-[searchEngine encodeWithCoder:]: unrecognized selector sent to instance 0x1a25b0

         

那么任何想法如何在兼容plist的数据中获取这些实体?

  
     

2) @try {registerDefaults}

     
    

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

  

我知道,很长的问题......但是:尝试{[我提供:详情]}; D

4 个答案:

答案 0 :(得分:35)

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

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

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

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

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

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

答案 1 :(得分:7)

目前使用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];
 }

答案 2 :(得分:6)

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

一些示例代码(稍微修改自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...
}

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

答案 3 :(得分:0)

我的模型将记录的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.uuidString即可将UUID保存为字符串。