My app has a user select a photo from the picker. I apply the selected image to a view and then I save it to a file and reference that file in user defaults so when the UserProfile is created that avatar is loaded in.
When I close the app and then start it again, the app loads the image from the file. After loading the image from the file, my app is crashing when I apply it to an Image view because it is seen as an __NSCFArray. There is no method scale on __NSCFArray. Why is it being cast to this class?
-[__NSCFArray scale]: unrecognized selector sent to instance 0x145260
* Terminating app due to uncaught exception
‘NSInvalidArgumentException’, reason: ‘[__NSCFArray scale]:
unrecognized selector sent to instance 0x145260’
Here is my code where the UIImage is created from a file:
@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;
}
Note: in my createThumbnail code I call this [_avatar isKindOfClass:[UIImage class] and it says it is a UIImage. But then when I set the view, it thinks it is an __NSCFArray. I don’t even understand how this is possible since the property is a UIImage *.
This is how the image is persisted
- (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");
}
}
To my knowledge I am not receiving a memory warning.
You are saving
autoreleasedobject (return byimageNamed:andimageWithContentsOfFile:) withoutretainingininit. You can replace that method with next one:You don’t need to
retainthis object anymore.Just
releaseit indealloc.In
setAvatar:you should alsoretainreturned byimageNamed:value :_avatar = [[UIImage imageNamed:DEFAULT_AVATAR_FILENAME] retain];