我正在尝试使用NSKeyedArchiver
/ NSKeyedUnarchiver
在文件中存储类属性的数据,以便在启动应用程序之间保持属性的状态。
我在MyClass.h中声明了这样的属性:
@property (nonatomic, weak) NSDictionary *myDictionary;
我在MyClass.m中创建了自定义getter和setter方法,以确保将NSDictionary写入磁盘:
-(NSDictionary *)myDictionary {
NSDictionary *dictionary;
NSString *path = [self pathToDataStore];
if (![[NSFileManager defaultManager] fileExistsAtPath:path]) {
dictionary = [NSDictionary dictionary];
} else {
NSData *archivedData = [NSData dataWithContentsOfFile:path];
dictionary = [NSKeyedUnarchiver unarchiveObjectWithData:archivedData];
}
return dictionary;
}
-(void)setMyDictionary:(NSDictionary *)dictionary {
NSString *path = [self pathToDataStore];
NSDictionary *rootObject = [NSDictionary dictionaryWithDictionary:dictionary];
[NSKeyedArchiver archiveRootObject:rootObject toFile:path];
self.myDictionary = dictionary;
}
这导致对[self setMyDictionary]
的无限循环调用,所以显然我做错了。但是问题是什么?
答案 0 :(得分:3)
而不是:
self.myDictionary = dictionary;
你应该这样做:
@synthesize myDictionary;
...
-(void)setMyDictionary:(NSDictionary *)dictionary {
...
myDictionary = dictionary
}
您的问题发生原因是:
self.myDictionary = dictionary;
等于
[self setMyDictionary:dictionary];
答案 1 :(得分:1)
answer from debris解释了为什么在setter中使用self.myDictionary
语法导致无限递归(因为“dot”语法只是再次调用setter)并指出相反,你应该在访问器方法中使用实例变量。
话虽如此,还有一些额外的观察。
您可以收紧现有代码。例如,为什么setter会创建一个新的归档字典?您可以归档传递给setter的dictionary
(如果归档因任何原因失败,也可以记录消息)。
-(void)setMyDictionary:(NSDictionary *)dictionary {
if (![NSKeyedArchiver archiveRootObject:dictionary toFile:[self pathToDataStore]])
NSLog(@"%s: archiveRootObject failed", __FUNCTION__);
_myDictionary = dictionary;
}
每次引用self.myDictionary
getter时,它都会从归档中重新检索,即使它已经被检索过。这是低效的,可能会导致一些意想不到的后果(例如if (self.myDictionary == self.myDictionary)...
将失败)。如果没有字典,您可能希望将getter定义为仅从归档中检索字典:
- (NSDictionary *)myDictionary {
if (!_myDictionary) {
NSString *path = [self pathToDataStore];
if ([[NSFileManager defaultManager] fileExistsAtPath:path]) {
_myDictionary = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
}
}
return _myDictionary;
}
注意,因为您已经定义了两种访问器方法,所以您可能希望有一条@synthesize
行明确定义遵循典型下划线约定的ivar:
@synthesize myDictionary = _myDictionary;
此外,使用weak
内存限定符很奇怪(如果不是这个类,谁拥有此对象?)。我建议将它strong
。