iPhone+;NSCoding/NSKeyedArchiver
在坚持我的应用程序设置类时,我在NSCoding和NSKeyedArchiver方面有一个小问题,我希望有人能发现一个问题,如果这是我的代码,我对Obj-C相对较新,但在多种语言中有丰富的编码经验,所以代码对我来说似乎没问题,但是 我有一个实例类来保存我的应用程序设置,该类本身是主应用程序委托的保留属性,它是通过iPhone+;NSCoding/NSKeyedArchiver,iphone,Iphone,在坚持我的应用程序设置类时,我在NSCoding和NSKeyedArchiver方面有一个小问题,我希望有人能发现一个问题,如果这是我的代码,我对Obj-C相对较新,但在多种语言中有丰富的编码经验,所以代码对我来说似乎没问题,但是 我有一个实例类来保存我的应用程序设置,该类本身是主应用程序委托的保留属性,它是通过 @interface AppDelegate : NSObject <UIApplicationDelegate> { Settings *settings;
@interface AppDelegate : NSObject <UIApplicationDelegate> {
Settings *settings;
[...]
}
@property (nonatomic, retain) Settings *settings;
[...]
如果我注释掉上面的行,那么应用程序每次都可以正常工作,但是如果我使用NSCoder和NSKeyedUnarchiver将项目从持久化设置中拉回来,则会在为编码为布尔属性的内容发送NSCFString选择器时抛出SIGARBT错误?Settings类定义为实现协议的NSObject
@interface Settings : NSObject <NSCoding>
加载设置后,将按如下方式使用相关属性:
SettingsViewController *settingsView = [[SettingsViewController alloc] initWithNibName:@"SettingsView" bundle:nil];
[self presentModalViewController:settingsView animated:[AppDelegate instance].settings.animateMenus];
[settingsView release];
**设置类的animateMenus成员现在将抛出以下内容:
-[NSCFString animateMenus]:发送到实例0xc712570 2010-10-15 11:12:51.828应用程序[900:207]*由于未捕获异常“NSInvalidArgumentException”,终止应用程序,原因:'-[NSCFString animateMenus]:发送到实例0xc712570的未识别选择器'
鉴于,采用'settings=[settings LoadSettings];'退出应用程序启动会消除该问题(但始终使用应用程序默认值)
加载和保存方法:
+ (Settings*) LoadSettings {
Settings *s = nil;
@try {
NSData *data = [[NSUserDefaults standardUserDefaults] objectForKey:@"settings"];
if (data == nil) {
s = [[Settings alloc] init];
[s Initialise];
[s SaveSettings];
}
else
s = (Settings*)[NSKeyedUnarchiver unarchiveObjectWithData:data];
}
@catch (NSException * e) {
NSLog(@"Error Loading Settings\n%@", [e reason]);
}
@finally {
return s;
}
}
// Saves the settings dictionary to the user's device documents folder..
- (void) SaveSettings {
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:self];
[[NSUserDefaults standardUserDefaults] setObject:data forKey:@"settings"];
}
Load是一种静态方法,设置的所有其他成员都是实例。您需要执行以下操作:
settings = [[Settings LoadSettings] retain];
这是因为在LoadSettings中,NSKeyedUnachiver的结果是一个自动释放的对象。它被释放:-)在那个位置创建了一个新对象,在本例中是一个NSString
编辑:
嗯,我刚注意到LoadSettings的一个主要问题,一开始我没有注意到:您混合了内存释放策略:在一个代码路径中,您返回未自动删除的[[Settings alloc]init]
的结果,而在另一个代码路径中,您保留自动删除的NSKeyedArchiver的结果。您需要确保只使用一个概念
由于方法名LoadSettings的名称中不包含alloc
、copy
或new
,因此惯例是它应该返回一个自动删除的对象。因此,你应该:
if (data == nil) {
s = [[Settings alloc] init];
[s Initialise];
[s SaveSettings];
[s autorelease];
}
else
...
太好了,谢谢!我认为,通过将静态LoadSettings方法返回的指针分配到app委托中的保留指针中,它将被保留,而不管它的初始发布类型如何。现在我对iPhone上的内存管理策略有了更多的了解。
settings = [[Settings LoadSettings] retain];
if (data == nil) {
s = [[Settings alloc] init];
[s Initialise];
[s SaveSettings];
[s autorelease];
}
else
...