【问题标题】:Storing NSMutableArray to NSUserDefaults将 NSMutableArray 存储到 NSUserDefaults
【发布时间】:2013-12-25 12:32:26
【问题描述】:

首先:大家圣诞快乐!自从我能够将数据存储到 NSUserDefaults 中已经有一段时间了。

在这种情况下,我想将 NSMutableArray 存储到 NSUserDefaults。我很清楚,您只能将不可变对象存储到此“文件”中。

我曾尝试使用以下代码加载 NSMutableArray:

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
self.mutableArray = [[NSMutableArray alloc] initWithArray: [defaults objectForKey:@"TestKey"]];

我正在使用以下代码来存储数据:

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSArray *tempArr = [NSArray arrayWithArray:self.mutableArray];
[defaults setObject:tempArr forKey:@"TestKey"];
[defaults synchronize];

不幸的是,模拟器退出并出现以下错误:

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSUserDefaults setObject:forKey:]: attempt to insert non-property list object (
"<MyObject: 0x10dfb40a0>"
) for key TestKey'

可变数组包含 NSObjects。

有人知道我在哪里搞砸了吗?

【问题讨论】:

  • self.mutableArray 中有什么内容?
  • self.mutableArray 包含由 NSString 元素组成的 NSObjects
  • nslog 记录 tempArr 的值并检查它是否包含数据
  • NSLog 打印:Temparr is: ("" )
  • NSUserDefaults 不能包含NSObjects,请参阅文档:默认对象必须是一个属性列表,即一个实例(或集合实例的组合):NSData 、NSString、NSNumber、NSDate、NSArray 或 NSDictionary。您必须将您的 NSObject 转换为其中之一。

标签: objective-c nsmutablearray nsuserdefaults


【解决方案1】:

你可以试试这个:

存档:

NSData *data = [NSKeyedArchiver archivedDataWithRootObject:YOUR_MUTABLE_ARRAY]; [[NSUserDefaults standardUserDefaults] setObject:data forKey:@"myarray"]; [[NSUserDefaults standardUserDefaults] 同步];

要取消归档:

NSData *data = [[NSUserDefaults standardUserDefaults] objectForKey:@"myarray"]; NSMutableArray *mArr = [NSKeyedUnarchiver unarchiveObjectWithData:data];

【讨论】:

  • 缺少自定义对象必须支持NSCoding 协议。
【解决方案2】:

您无法将 tempArr 保存到 NSUserDefaults,因为正如您在评论中显示的那样,该数组包含 MyObject 的子类,这是自定义对象。如果你想把它保存到 NSUserDefaults 你应该实现 NSCoding 协议并添加两个方法:

- (void)encodeWithCoder:(NSCoder *)encoder {
    //Encode all yours properties, vars
    [encoder encodeObject:self.property1 forKey:@"property1"];
    [encoder encodeObject:self.property2 forKey:@"property2"];
}

- (id)initWithCoder:(NSCoder *)decoder {
    if((self = [super init])) {
        //decode all yours properties, vars
        self.property1 = [decoder decodeObjectForKey:@"property1"];
        self.property2 = [decoder decodeObjectForKey:@"property2"];
    }
    return self;

但是 NSUserDefaults 的设计目的只是存储简单数据,如果您想保存更多自定义对象,您应该考虑将其保存到文件中,看看 NSKeyedArchiver 可能更适合您。请记住,如果您想使用 NSKeyedArchiver 保存自定义对象,该对象也应符合 NSCoding 协议,并且您还必须在上面添加这两个方法。

【讨论】:

    【解决方案3】:

    NSUserDefaults 无法处理自定义对象。

    来自 Apple 文档:

    默认对象必须是属性列表,即(或 对于集合实例的组合):NSData,NSString, NSNumber、NSDate、NSArray 或 NSDictionary。如果你想存储任何 其他类型的对象,您通常应该将其归档以创建一个 NSData 的实例。

    对于自定义对象,要么转换为这些对象之一,要么为类实现NSCoder 协议以创建NSData 表示。

    对于多于少量的参数,最佳选择是将CoreDataNSKeyedArchiver 保存到 Documents 目录中的文件中。

    【讨论】:

      【解决方案4】:

      您的两个选择是:

      1. MyObject 中实现NSCoding,然后使用NSKeyedArchiver

      2. 使用 CoreData

      一个很好的教程和两者的比较可以在这里找到:http://nshipster.com/nscoding/

      【讨论】:

      • 简洁的答案和一个很好的链接。不幸的是,它没有回答问题,也没有回答为什么,cmets 和/或其他答案对于提供必要的上下文是必要的。考虑添加为什么 OP 的 NSUserDefaults 不起作用。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-04-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多