2011-09-19 55 views
0

我的應用程序有一個用戶從選擇器中選擇一張照片。我將選定的圖像應用到視圖,然後將其保存到文件中,並以用戶默認值引用該文件,以便在創建用戶配置文件時加載頭像。UIImage *是一個__NSCFArray而不是一個UIImage

當我關閉應用程序然後重新啓動它時,該應用程序從文件加載圖像。從文件加載圖像後,我的應用程序在應用到Image視圖時崩潰,因爲它被視爲__NSCFArray。 __NSCFArray上沒有方法縮放。爲什麼這個課程被投入了?

- [__ NSCFArray規模]:無法識別的選擇發送到實例0x145260

*終止應用程序由於未捕獲的異常 'NSInvalidArgumentException' 的,原因是:「[__NSCFArray規模]: 無法識別的選擇發送到實例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

您在init沒有retaining保存autoreleased對象(返程由imageNamed:imageWithContentsOfFile:)。你可以用下一個替換方法:

- (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];

+0

Tx @Nekto。我知道它正在盯着我。 – vesselhead

3

您正在將自動釋放對象分配給您的ivars。最有可能的是他們正在被釋放,然後當你嘗試訪問其中一個UIImage它恰好是在同一個內存地址的NSArray。

_username = (NSString *)[userDefaults objectForKey:USERNAME_KEY]; 
... 
_avatar = [UIImage imageWithContentsOfFile:filename]; 
... 
_avatar = [UIImage imageNamed:DEFAULT_AVATAR_FILENAME]; 

您需要保留它們。

+0

+1看起來像有人剛剛經歷了這個問題去了,倒在他們的道路投票的一切! – Joe

+0

我沒有投下任何東西。離線了幾個小時。無論如何,我從不投票 - 還沒有足夠的經驗。 – vesselhead

+0

現在的問題是......如果他們都好,我選擇哪個答案? – vesselhead