I am intending to download and encode an image as shown below.
However I am getting the error -[NSKeyedArchiver encodeObject:forKey:]: archiver has finished; cannot encode anything more’. Can anyone explain why this error occurred and how I can I resolve it?
- (void)encodeWithCoder:(NSCoder *)encoder
{
dispatch_queue_t downloadQueue = dispatch_queue_create("image downloader", NULL);
dispatch_async(downloadQueue, ^{
NSURL *url = [NSURL URLWithString:self.avatar_url];
NSData *data = [NSData dataWithContentsOfURL:url];
dispatch_async(dispatch_get_main_queue(), ^{
self.avatar = [[[UIImage alloc] initWithData:data] autorelease];
[encoder encodeObject:UIImagePNGRepresentation(self.avatar) forKey:@"avatar"];
});
});
}
Error Stack
2011-11-03 00:08:32.645 onethingaday[6897:207] *** Terminating app due to uncaught exception 'NSInvalidArchiveOperationException', reason: '*** -[NSKeyedArchiver encodeObject:forKey:]: archiver has finished; cannot encode anything more'
*** First throw call stack:
(0x29de052 0x26ddd0a 0x2986a78 0x29869e9 0x16e1d40 0x9fdd 0x1d33445 0x1d354f0 0x2915833 0x2914db4 0x2914ccb 0x2d57879 0x2d5793e 0xd89a9b 0x290d 0x2885 0x1)
You should not use an asynchronous method in
-encodeWithCoder:. The reason is simple. The function is usually called like this (in the lower level):Your
-encodeWithCoder:is asynchronous with GCD. Therefore line A will return before anything happens, and then line B will be executed (still your scheduled function will not be called). This finish the archiver and prevents further encoding on it.Later, the asynchronous method is allowed to start, and you download the image and convert it into PNG etc… and finally tell the
encoderto-encodeObject:forKey. But this is already too late — the archiver has already been finished long time before! Therefore the exception is thrown.To avoid this, you should ensure not to call
-encodeObject:forKeyasynchronously. The GCD codes should be put outside of the-encodeWithCoder:method, i.e. the image should be completely available before performing the archiving.