错误:'存档已完成;无法编码更多内容
我打算下载并编码图像,如下所示。
但是我收到错误 -[NSKeyedArchiverencodeObject:forKey:]: archiver has finish;无法编码更多内容”。谁能解释为什么会出现此错误以及如何解决它?
- (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"];
});
});
}
错误堆栈
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)
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)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您不应在
-encodeWithCoder:
中使用异步方法。原因很简单。该函数通常这样调用(在较低级别):您的
-encodeWithCoder:
与 GCD 异步。因此,A行将在任何事情发生之前返回,然后B行将被执行(仍然不会调用您的预定函数)。这完成了归档器并防止对其进行进一步编码。稍后,允许启动异步方法,您下载图像并将其转换为 PNG 等...最后告诉
encoder
为-encodeObject:forKey
。但这已经太晚了——存档器早就完成了!因此抛出异常。为了避免这种情况,您应该确保不要异步调用
-encodeObject:forKey
。 GCD 代码应该放在-encodeWithCoder:
方法的外部,即在执行归档之前图像应该完全可用。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
encoder
to-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:forKey
asynchronously. The GCD codes should be put outside of the-encodeWithCoder:
method, i.e. the image should be completely available before performing the archiving.