1

I have seen different question on stackoverflow related to this topic. Some says that NSCoding does not conform with UIImage and other says that with iOS 5, it does conform.

I want to persist images in my app. I am using encode and decode methods and everything (title, labels etc) are persisting but NOT the images.

- (void)encodeWithCoder:(NSCoder *)aCoder
{
    [aCoder encodeObject:title forKey:@"title"];
    [aCoder encodeObject:link forKey:@"link"];
    [aCoder encodeObject:creator forKey:@"creator"];
    [aCoder encodeObject:pubDate forKey:@"pubDate"];
  //  [aCoder encodeObject:thumbnail forKey:@"thumbnail"];
    [aCoder encodeObject:UIImagePNGRepresentation(thumbnail) forKey:@"thumbnail"];
}

- (id)initWithCoder:(NSCoder *)aDecoder
{
    self = [super init];
    if (self)
    {
        [self setTitle:[aDecoder decodeObjectForKey:@"title"]];
        [self setLink:[aDecoder decodeObjectForKey:@"link"]];
        [self setCreator:[aDecoder decodeObjectForKey:@"creator"]];
        [self setPubDate:[aDecoder decodeObjectForKey:@"pubDate"]];
        [self setThumbnail:[aDecoder decodeObjectForKey:@"thumbnail"]];        
    }
    return self;
}

I am also using UIPNGRepresentation but its not working. Can someone help me with this.

Thanks.

Jessica
  • 1,508
  • 15
  • 25

2 Answers2

7

You're not encoding an image. UIImagePNGRepresentation() returns an NSData object. NSData conforms to NSSecureCoding. I haven't worked with that before, but the docs say that you have to decode it like this:

id obj = [decoder decodeObjectOfClass:[MyClass class] forKey:@"myKey"];

After Edit: The above doesn't appear to be necessary. I used the following code in a test app, and both approaches to encoding and decoding an image worked.

- (void)encodeWithCoder:(NSCoder *)aCoder
{
    [aCoder encodeObject:self.name forKey:@"personName"];
    [aCoder encodeObject:self.image2 forKey:@"thumbnail2"];
    [aCoder encodeObject:UIImagePNGRepresentation(self.image1) forKey:@"thumbnail"];
}

- (id)initWithCoder:(NSCoder *)aDecoder
{
    self = [super init];
    if (self)
    {
        [self setName:[aDecoder decodeObjectForKey:@"personName"]];
        [self setImage2:[aDecoder decodeObjectForKey:@"thumbnail2"]];
        [self setImage1:[UIImage imageWithData:[aDecoder decodeObjectForKey:@"thumbnail"]]];
    }
    return self;
}

As Aleph said, the problem must be elsewhere.

rdelmar
  • 103,982
  • 12
  • 207
  • 218
  • I have also used "[self setThumbnail:[UIImage imageWithData:[aDecoder decodeObjectForKey:@"thumbnail"]]];" but thats also not working – Jessica Jan 14 '13 at 19:51
  • This is not fully encoding and decoding the UIImage because it is not encoding and then decoding the UIImage.scale property. – algal May 16 '14 at 15:15
  • You can use imageWithData:scale: for that purposes – Artem Zaytsev Sep 16 '15 at 17:59
2

Try this:


- (void)encodeWithCoder:(NSCoder *)aCoder
{
    [aCoder encodeObject:title forKey:@"title"];
    [aCoder encodeObject:link forKey:@"link"];
    [aCoder encodeObject:creator forKey:@"creator"];
    [aCoder encodeObject:pubDate forKey:@"pubDate"];
    NSData* data = UIImagePNGRepresentation(thumbnail);
    NSLog(@"Data length: %d", data.length);
    [aCoder encodeObject:data forKey:@"thumbnail"];
}

- (id)initWithCoder:(NSCoder *)aDecoder
{
    self = [super init];
    if (self)
    {
        [self setTitle:[aDecoder decodeObjectForKey:@"title"]];
        [self setLink:[aDecoder decodeObjectForKey:@"link"]];
        [self setCreator:[aDecoder decodeObjectForKey:@"creator"]];
        [self setPubDate:[aDecoder decodeObjectForKey:@"pubDate"]];
        NSData* data = [aDecoder decodeObjectForKey:@"thumbnail"];
        NSLog(@"Data length: %d", data.length);
        [self setThumbnail:[UIImage imageWithData:data]];        
    }
    return self;
}
Alejandro
  • 3,726
  • 1
  • 23
  • 29
  • just tried the code you provided. It didn't work. To my surprise, the data length in the console is zero. – Jessica Jan 14 '13 at 20:21
  • Is it zero when encoding? Try logging the thumbnail object. – Alejandro Jan 14 '13 at 20:42
  • I have used "NSLog(@"Data length 1: %d", data.length);" in encodeWithCoder and NSLog(@"Data length 2: %d", data.length); in initWithCoder. Both logs gives '0' in console – Jessica Jan 14 '13 at 20:49
  • If you get 0 on encoding that means that either the image is nil or it is failing to encode as PNG. Check that you have a valid image on encode. If you encode 0 bytes you will, of course, get 0 bytes on decode. – Alejandro Jan 14 '13 at 20:51
  • If i remove the cache by resetting the content, the first time it fetches new entries, images does show in the tableview but when i fetch it again and it fetches the entries from the cache, then it does not show images which means the images are not nil, its failing to encode them and i don't know why. – Jessica Jan 14 '13 at 21:10
  • logging just thumbnail is giving NULL. What should i do now? – Jessica Jan 14 '13 at 21:19
  • 1
    If your image is nil then you have a problem somewhere else. Maybe create a new question and post more code. – Alejandro Jan 14 '13 at 23:11