“尝试设置非属性列表对象....”NSMutableDictionary与自定义类

时间:2013-12-24 01:12:58

标签: ios objective-c

我有一个名为ServerModule的自定义类,它是NSObject的子类。我基本上将所有这些ServerModule存储在NSMutableDictionary中的键值对中。然后将字典存储在NSUserDefaults中。我了解到NSUserDefaults只在访问对象时返回对象的不可变版本,因此我将字典初始化更改为:

_AllModules = [[NSMutableDictionary alloc]initWithDictionary:[_editServerModules objectForKey:@"AllModules"]]; //initialize a copy of AllModules dictionary

现在,我只是尝试将自定义ServerModule对象存储在此字典中,然后进行同步。以下代码尝试执行此操作:

//Create new ServerModule
        ServerModule* newServer = [[ServerModule alloc]initWithUUID];
        newServer.name = self.tf_name.text;
        newServer.ip = self.tf_ip.text;
        newServer.port = self.tf_port.text;
        newServer.username = self.tf_user.text;
        newServer.password = self.tf_pass.text;
        //Add the ServerModule to AllModules dictionary with the key of its identifier
        [_AllModules setObject:newServer forKey:newServer.identifier];
        [self updateData];
        [_editServerModules synchronize];

标识符是在ServerModule的构造函数中设置的字符串。以下是updateData的代码。

[_editServerModules setObject:_AllModules forKey:@"AllModules"];

如果您想知道,@"AllModules"处的对象在AppDelegate中初始化如下:

NSMutableDictionary* AllModules = [[NSMutableDictionary alloc]init];

再一次,这是我在尝试保存某些内容时遇到的错误:

Attempt to set a non-property-list object {
    "42E9EEA0-9051-4E2A-81EA-DC8FC5639C26" = "<ServerModule: 0x8ac4e50>";
} as an NSUserDefaults value for key AllModules

感谢您的帮助!

〜Carpetfizz

1 个答案:

答案 0 :(得分:17)

您只能在NSUserDefaults中存储属性列表类型(数组,数据,字符串,数字,日期,字典)或网址。这意味着所有内容(包括任何嵌套字典值)都必须是属性列表类型。您需要在ServerModule对象上实施NSCoding协议,然后在存储数据之前使用NSKeyedArchiver序列化数据,并在阅读后NSKeyedUnarchiver对数据进行收缩退出NSUserDefaults

例如,假设您显示的属性存在于ServerModule个对象上,我会将以下NSCoding协议方法添加到您的ServerModule实现中:

#pragma mark - NSCoding support
-(void)encodeWithCoder:(NSCoder*)encoder {
    [encoder encodeObject:self.name forKey:@"name"];
    [encoder encodeObject:self.ip forKey:@"ip"];
    [encoder encodeObject:self.port forKey:@"port"];
    [encoder encodeObject:self.username forKey:@"username"];
    [encoder encodeObject:self.password forKey:@"password"];
}

-(id)initWithCoder:(NSCoder*)decoder {
    self.name = [decoder decodeObjectForKey:@"name"];
    self.ip = [decoder decodeObjectForKey:@"ip"];
    self.port = [decoder decodeObjectForKey:@"port"];
    self.username = [decoder decodeObjectForKey:@"username"];
    self.password = [decoder decodeObjectForKey:@"password"];
    return self;
}

当然,你需要序列化:

NSData* archivedServerModules = [NSKeyedArchiver archivedDataWithRootObject:_AllModules];
[_editServerModules setObject:archivedServerModules forKey:@"AllModules"];

适当放气:

NSData* archivedServerModules = [_editServerModules objectForKey:@"AllModules"];
NSDictionary* serverModules = [NSKeyedUnarchiver unarchiveObjectWithData:archivedServerModules];

希望这可以让你了解我在说什么。