UIImage * 是 __NSCFArray 而不是 UIImage
Posted
技术标签:
【中文标题】UIImage * 是 __NSCFArray 而不是 UIImage【英文标题】:UIImage * is a __NSCFArray instead of a UIImage 【发布时间】:2011-09-19 18:48:54 【问题描述】:我的应用让用户从选择器中选择一张照片。我将所选图像应用于视图,然后将其保存到文件并在用户默认值中引用该文件,以便在创建 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 class],它说它是 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");
据我所知,我没有收到内存警告。
【问题讨论】:
【参考方案1】:您正在将自动释放的对象分配给您的 ivars。很可能它们正在被释放,然后当您尝试访问其中一个 UIImage 时,它恰好是位于同一内存地址的 NSArray。
_username = (NSString *)[userDefaults objectForKey:USERNAME_KEY];
...
_avatar = [UIImage imageWithContentsOfFile:filename];
...
_avatar = [UIImage imageNamed:DEFAULT_AVATAR_FILENAME];
你需要保留它们。
【讨论】:
+1 看起来有人刚刚完成了这个问题,并在他们的道路上投了反对票! 我没有投反对票。离线几个小时。无论如何,我从不投反对票——还没有足够的经验。 现在的问题是……如果他们没问题,我应该选择哪个答案? 谢谢。我对这两个答案都投了赞成票,并将答案交给了@Nekto,以显示保留。似乎很蹩脚,你不能给出两个正确的答案。 我刚刚了解了更多有关系统的信息,发现您实际上首先做出了回应。抱歉,阿尔伯特没有检查您的答案。我喜欢这个网站。有史以来最好的讨论论坛。你们太棒了。【参考方案2】:您正在保存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];
【讨论】:
发送@Nekto。我知道它正盯着我的脸。以上是关于UIImage * 是 __NSCFArray 而不是 UIImage的主要内容,如果未能解决你的问题,请参考以下文章
由于未捕获的异常“NSRangeException”而终止应用程序,原因:“-[__NSCFArray objectAtIndex:]: index (14) beyond bounds (14)”
-[__NSCFArray bytes]: 无法识别的选择器发送到实例
从 plist 读取而不是代码数组:[NSCFArray objectForKey:]: unrecognized selector