我的应用让用户从选择器中选择一张照片。我将所选图像应用于视图,然后将其保存到文件中并以用户默认值引用该文件,以便在创建UserProfile时加载头像。
当我关闭应用程序然后再次启动时,应用程序会加载文件中的图像。从文件加载图像后,我的应用程序在将其应用于图像视图时崩溃,因为它被视为__NSCFArray。 __NSCFArray上没有方法比例。为什么要投这个班级?
- [__ NSCFArray scale]:无法识别的选择器发送到实例0x145260
* 由于未捕获的异常而终止应用 'NSInvalidArgumentException',原因:'[_ _ NSCFArray scale]: 无法识别的选择器发送到实例0x145260'
这是我的代码,其中UIImage是从文件创建的:
@implementation UserProfile
- (id) init {
self = [super init];
if(self) {
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
_username = (NSString *)[userDefaults objectForKey:USERNAME_KEY];
NSString *filename = (NSString *) [userDefaults objectForKey:@"AvatarFilename"];
NSLog(@"filename from user defaults: %@",filename);
if (filename) {
_avatar = [UIImage imageWithContentsOfFile:filename];
if (!_avatar) NSLog(@"LOGERROR: avatar was not created from file");
_customAvatar = TRUE;
} else {
_customAvatar = FALSE;
_avatar = [UIImage imageNamed:DEFAULT_AVATAR_FILENAME];
if (!_avatar) NSLog(@"LOGERROR: avatar was not created from default");
}
[self createThumbnail];
}
return self;
}
注意:在我的createThumbnail代码中,我称之为[_avatar isKindOfClass:[UIImage类],它说它是一个UIImage。但是当我设置视图时,它认为它是__NSCFArray。我甚至不明白这是怎么可能的,因为该属性是UIImage *。
这就是图像的持久性
- (void) setAvatar:(UIImage *)image
{
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
NSString *filename = nil;
if (image) {
if (_avatar) [_avatar release];
_avatar = [image retain];
_customAvatar = TRUE;
filename = [NSString stringWithFormat:@"%@/%@",[MyUtilities applicationDocumentsDirectory],AVATAR_FILENAME];
if (![UIImagePNGRepresentation(image) writeToFile:filename atomically:YES])
NSLog(@"LOGERROR: Failure to write avatar file");
else NSLog(@"saved avatar to PNG file");
} else {
NSLog(@"setting default avatar");
_avatar = [UIImage imageNamed:DEFAULT_AVATAR_FILENAME];
_customAvatar = FALSE;
}
[userDefaults setObject:filename forKey:AVATAR_KEY];
// TODO If performance is crucial, consider creating a default thumbnail as well
[self createThumbnail];
if(![userDefaults synchronize])
{
NSLog(@"LOGERROR: Failure to synchronize userDefaults");
}
}
据我所知,我没有收到记忆警告。
答案 0 :(得分:3)
您正在为自己的ivars分配自动释放的对象。最有可能的是它们被释放,然后当你尝试访问其中一个UIImage时,它恰好是同一内存地址的NSArray。
_username = (NSString *)[userDefaults objectForKey:USERNAME_KEY];
...
_avatar = [UIImage imageWithContentsOfFile:filename];
...
_avatar = [UIImage imageNamed:DEFAULT_AVATAR_FILENAME];
你需要保留它们。
答案 1 :(得分:1)
您正在autoreleased
中保存imageNamed:
个对象(imageWithContentsOfFile:
和retaining
返回)而init
没有- (id) init {
self = [super init];
if(self) {
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
_username = (NSString *)[userDefaults objectForKey:USERNAME_KEY];
NSString *filename = (NSString *) [userDefaults objectForKey:@"AvatarFilename"];
NSLog(@"filename from user defaults: %@",filename);
if (filename) {
_avatar = [[UIImage imageWithContentsOfFile:filename] retain];
if (!_avatar) NSLog(@"LOGERROR: avatar was not created from file");
_customAvatar = TRUE;
} else {
_customAvatar = FALSE;
_avatar = [[UIImage imageNamed:DEFAULT_AVATAR_FILENAME] retain];
if (!_avatar) NSLog(@"LOGERROR: avatar was not created from default");
}
[self createThumbnail];
}
return self;
}
。您可以用下一个方法替换该方法:
retain
您不再需要release
此对象了。
dealloc
只需setAvatar:
。
在retain
中,您还应imageNamed:
返回_avatar = [[UIImage imageNamed:DEFAULT_AVATAR_FILENAME] retain];
值:{{1}}