我尝试将我创建的自定义对象类添加到nsuserdefaults数组中,但它始终保持为空。我得到的日志是:
“请注意,属性列表中的字典和数组也必须只包含属性值”
我的代码是:
-(void)addProgramWithName:(NSString *)nameOfProgram andWithArrayOfIntervals:(NSMutableArray *)arrayOfIntervals{
Program *tempProgram = [[Program alloc] init];
tempProgram.nameOfProgram = nameOfProgram;
tempProgram.arrayOfIntervals = arrayOfIntervals;
NSMutableArray *tempArrayOfPrograms = [NSMutableArray arrayWithArray: [[NSUserDefaults standardUserDefaults] arrayForKey: @"arrayOfPrograms"]];
[tempArrayOfPrograms addObject:tempProgram];
[defaults setObject:tempArrayOfPrograms forKey:@"arrayOfPrograms"];
[defaults synchronize];
}
原因可能是什么?
答案 0 :(得分:1)
问题的原因是日志消息所说的 - 对于属性列表,您添加到数组(或字典)的任何对象必须是属性值(字符串,数字,日期和数组/字典)。
因此,在您的情况下,您似乎已从用户默认值中读取了值,现在您想要将一些自定义对象添加到您已读入的值中。
如果你不打算将修改后的数组写回用户默认值,那么这种方法没有任何问题(虽然这对我来说是一种有点过时的数据结构方法)。
另一方面,如果需要重新写入数据,则只应在数组中存储属性值。对于更复杂的对象,可以通过使用键和值在字典对象中对其进行编码来实现。
根据您的需要,Core Data可能更适合您的数据。
答案 1 :(得分:0)
将数组或字典存储到NSUserDefaults时,它会压缩到磁盘上的plist中。这意味着您的自定义对象需要转换为可以存储在plist中的格式。有很多方法可以做到这一点,具体取决于您的对象所拥有的数据类型,但这种方法几乎适用于任何自定义对象,并且应该非常强大。
感谢Apple设计精良的框架,它实现起来非常简单:)
在Program.h
添加<NSCoding>
协议。
@interface Program : NSObject <NSCoding>
然后在Program.m
中确保您实施以下方法。
#pragma mark - NSCoding
-(void)encodeWithCoder:(NSCoder *)encoder
{
// For each of the Program's properties that needs to be stored.
[encoder encodeObject:self.property forKey:@"PropertyKey"];
}
-(id)initWithCoder:(NSCoder *)decoder
{
if (self=[super init]) {
self.property = [decoder decodeObjectForKey:@"PropertyKey"];
}
return self;
}
此协议及其方法允许您自定义对象的动态编码和解码。这很重要,因此我们可以将您的对象设置为正确的格式。
接下来,我们将在存储之前归档您的数组。所以用这个替换你的代码:
// Old Line
// [defaults setObject:tempArrayOfPrograms forKey:@"arrayOfPrograms"];
// New Lines
id archivedObject = [NSKeyedArchiver archivedDataWithRootObject:tempArrayOfPrograms];
[defaults setObject:archivedObject forKey:@"arrayOfPrograms"];
现在最后一步是确保你在出路时取消归档。因此,无论您从NSUserDefaults
加载数组,都要确保取消归档。
// Get the archived array.
id archivedObject = [[NSUserDefaults standardUserDefaults] objectForKey:@"arrayOfPrograms"];
// Unarchive the array.
NSArray *unarchivedArray = [NSKeyedUnarchiver unarchiveObjectWithData:archivedObject];
// Its already a mutable array if you put a mutable array in but just to be safe.
NSMutableArray *arrayFromDefaults = [NSMutableArray arrayWithArray:unarchivedArray];