Ios 为什么不允许'NSUserDefaults'存储自定义类的对象?

Ios 为什么不允许'NSUserDefaults'存储自定义类的对象?,ios,swift,nsuserdefaults,swift3,Ios,Swift,Nsuserdefaults,Swift3,我已经看到,除了数组,字典,字符串,NSData,NSNumber,Bool,NSDate之外,nsserdefaults不允许对象。但是 为什么不允许存储其他对象 如果我需要将某些属性存储为单个对象,该怎么办?如果我使用字典,我必须把键写在我用来存储值的地方。那么,还有什么其他选择呢 如果Apple允许其他对象也存储,会出现什么问题 如果我们使用CoreData而不是NSUserDefaults呢。我知道NSUserDefaults在全球范围内可用 如果应用程序被终止,那么在我们重新启动应用

我已经看到,除了
数组
字典
字符串
NSData
NSNumber
Bool
NSDate
之外,nsserdefaults不允许对象。但是

  • 为什么不允许存储其他对象
  • 如果我需要将某些属性存储为单个对象,该怎么办?如果我使用字典,我必须把键写在我用来存储值的地方。那么,还有什么其他选择呢
  • 如果
    Apple
    允许其他对象也存储,会出现什么问题
  • 如果我们使用
    CoreData
    而不是
    NSUserDefaults
    呢。我知道
    NSUserDefaults
    在全球范围内可用
  • 如果应用程序被终止,那么在我们重新启动应用程序之后,让价值在全球范围内可用的最佳方式是什么?
正如@Hoa所建议的,之前我忘了提及
NSCoding
选项

  • 如果自定义类中有许多属性,我们是否需要使用
    NSCoding
    方法对它们进行编码和解码

只要符合NSCoding协议,就可以将任何对象保存到plist文件中

您可以使用类似于以下内容的代码:

+(id) readObjectFromFile:(NSString*) sFileName
{
    return [NSKeyedUnarchiver unarchiveObjectWithFile:sFileName];
}


+(bool) saveObject:(id <NSCoding>) anObject ToFile:(NSString*) sFileName
{
    NSData * data = [NSKeyedArchiver archivedDataWithRootObject:anObject];
    NSError * error;
    [data writeToFile:sFileName options:NSDataWritingAtomic error:&error];
    if (error)
        {
            NSLog(@"Save Cats Data error: %@", error.description);
            return NO;
        }
    return YES;
}
要了解有关NSCoding协议的更多信息,请阅读:

NSUserDefaults背后的意图是保存与应用程序状态相关的上下文数据,例如保存用户的首选项、用户停止使用应用程序时的状态(以便在启动时可以返回该状态)、登录会话数据等

核心数据是存储持久数据的一种更合适的方式,您可以根据需要映射数据模型,并有更广泛的选项来保存数据类型

虽然NSUserDefaults在“任何地方”都可用,但这不应成为决定这是否是保存数据的更好选项的转折点

您可以编写一个充当数据提供程序的单例类,以便能够以与访问NSUserDefaults共享实例相同的方式访问数据。您只需要记住,这个类或模块应该只做一件事,充当模型和实现之间的接口,因此您不需要在这个类中存储任何对象,只需要使用它来传递请求以获取数据并将数据保存到CoreData

这个类可以是这样的:

class CoreDataProvider {

    static let sharedInstance = SUProvider()

     let managedObjectContext : NSManagedObjectContext
     let sortDescriptor: NSSortDescriptor
     let fetchRequest: NSFetchRequest

     private init(){
         managedObjectContext = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
         fetchRequest = NSFetchRequest(entityName: "MyObject")
         sortDescriptor = NSSortDescriptor (key:"objectAttribute", ascending:true)

         self.fetchRequest.sortDescriptors = [self.sortDescriptor]
     }

     func getSavedObjects() -> [MyObject]? {
        fetchRequest.sortDescriptors = [sortDescriptor]

        do {
            return try self.managedObjectContext.executeFetchRequest(fetchRequest) as? [MyObject]
        } catch {
            print("no records found")
        }
    }
}
func getAllRecords() {
    let records = CoreDataProvider.sharedInstance.getSavedObjects()
    //- Do whatever you need to do
}
您会像这样使用它:

class CoreDataProvider {

    static let sharedInstance = SUProvider()

     let managedObjectContext : NSManagedObjectContext
     let sortDescriptor: NSSortDescriptor
     let fetchRequest: NSFetchRequest

     private init(){
         managedObjectContext = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext
         fetchRequest = NSFetchRequest(entityName: "MyObject")
         sortDescriptor = NSSortDescriptor (key:"objectAttribute", ascending:true)

         self.fetchRequest.sortDescriptors = [self.sortDescriptor]
     }

     func getSavedObjects() -> [MyObject]? {
        fetchRequest.sortDescriptors = [sortDescriptor]

        do {
            return try self.managedObjectContext.executeFetchRequest(fetchRequest) as? [MyObject]
        } catch {
            print("no records found")
        }
    }
}
func getAllRecords() {
    let records = CoreDataProvider.sharedInstance.getSavedObjects()
    //- Do whatever you need to do
}

存储对象的临时方法是创建字典或数组的json字符串。我在一些低规模的应用程序中使用过它。然后,您可以将这些字符串存储在NSUserDefault..中,当需要使用它时,您可以提取它,并且可以使用对象映射器库,该库将自动将json数据映射到对象类型

例如,您可以在类扩展中创建一个函数,在需要时随时将json数据解析为对象

我建议仅在小规模应用程序中使用上述方法。如果你要开发高流量/大规模的应用程序,你可能需要查看核心数据甚至SQlite3

请随便问任何问题


当然,您可以使用NSCoding方法存储自定义对象。我想最好的前男友之一就在这里——感谢你为我添加了Swift版本。