0

我尝试将我创建的自定义对象类添加到 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];

}

可能是什么原因?

4

2 回答 2

1

问题的原因是日志消息所说的 - 对于属性列表,您添加到数组(或字典)的任何对象都必须是属性值(字符串、数字、日期和数组/字典)。

因此,在您的情况下,您似乎已经从用户默认值中读取了值,现在您想要将一些自定义对象添加到您读取的值中。

如果您不打算将修改后的数组写回用户默认值,那么这种方法没有任何问题(尽管它让我觉得它是一种对数据结构有些狂热的方法)。

另一方面,如果您需要将数据写回,您应该只将属性值存储在数组中。对于更复杂的对象,可以通过将其编码到带有键和值的字典对象中来实现。

不过,根据您的需求,Core Data 可能更适合您的数据。

于 2013-02-11T16:25:41.270 回答
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];
于 2013-02-11T16:27:27.130 回答