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: 返回)而不在retaininginit。您可以将该方法替换为下一个:

- (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 这个对象了。 只需releasedealloc

setAvatar: 中,您还应该retainimageNamed: 返回值:_avatar = [[UIImage imageNamed:DEFAULT_AVATAR_FILENAME] retain];

【讨论】:

发送@Nekto。我知道它正盯着我的脸。

以上是关于UIImage * 是 __NSCFArray 而不是 UIImage的主要内容,如果未能解决你的问题,请参考以下文章

由于未捕获的异常“NSRangeException”而终止应用程序,原因:“-[__NSCFArray objectAtIndex:]: index (14) beyond bounds (14)”

-[__NSCFArray bytes]: 无法识别的选择器发送到实例

[NSCFArray 长度]:发送到实例的无法识别的选择器

从 plist 读取而不是代码数组:[NSCFArray objectForKey:]: unrecognized selector

[NSCFArray 行]:无法识别的选择器发送到实例 0x3953a20

iOS_UIImage_图片剪切