Objective-C:UIImageWriteToSavedPhotosAlbum()+ asynchronous = problems [英] Objective-C: UIImageWriteToSavedPhotosAlbum() + asynchronous = problems

查看:303
本文介绍了Objective-C:UIImageWriteToSavedPhotosAlbum()+ asynchronous = problems的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

更新:此处还报告了此问题,并对原因进行了更详细的处理:



UIImageWriteToSavedPhotosAlbum只保存5张图片(共10张)为什么?



在我的情况下,错误是:Write busy - 这似乎是一个与设备速度相关的问题。可能有一些解决方案涉及手动处理线程或类似 - 但是,从汤米的答案下面,我序列化图像的保存,并解决这个问题。



~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~



情况:



我尝试使用for循环将大图像集合保存到相机胶卷图像取决于用户输入 - 可以是1,2,3,或理论上几百)。图像由 NSSet (尽管我可以很容易地做一个 NSArray )指向,而 NSSet 在for循环完成后设置为 nil



我使用 UIImageWriteToSavedPhotosAlbum()在一个分离的线程上保存图像(使用 NSThread detachNewThreadSelector:toTarget:withObject:类方法),并在主线程上启动 UIActivityIndi​​cator b

问题:



当我尝试保存超过〜5时,在日志中输出此错误:



*** - [NSKeyedUnarchiver initForReadingWithData:]:data is NULL p>

例如,假设我导出了9张图片。 for循环将遍历所有9个图像(由NSLogging确认),但我会遇到上述错误的4次迭代(只有5个图像保存到相机胶卷)。



如果我在循环中添加一个断点,并且在每次迭代之间等待一两秒,那么它们都会被正确保存,而不会引起注意。



根据我的日志和观察结果, code> UIImageWriteToSavedPhotosAlbum()显然是异步运行,并且以某种方式太慢跟上我的应用程序。



一个简单的方法来强制它同步运行(理想地在主线程)?我一直在试验添加引用计数到我想要保存的图像,但(1)这感觉黑客,和(2)我没有解决这个问题,无论如何。



任何建议都会很好。谢谢!

解决方案

如果你不想一次性写多个图像,可以使用 UIImageWriteToSavedPhotosAlbum 的完成目标和选择器来实现尾递归的形式。类似:

   - (void)writeSetToSavedPhotosAlbum:(NSMutableSet *)images 
{
if [image count])return;

UIImage * imageToSave = [[[anyObject] retain] autorelease];
[images removeObject:imageToSave];
NSLog(@I will now write image%@,imageToSave);

UIImageWriteToSavedPhotosAlbum(
imageToSave,
self,
@selector(writeSetToSavedPhotosAlbum :),
images);
}

编辑:也许值得看看你是否得到相同的结果, code> ALAssetsLibrary 的 -writeImageToSavedPhotosAlbum:orientation:completionBlock: 块完成,所以更直接的工作。


Update: This problem was also reported here, with a more detailed treatment of the cause:

UIImageWriteToSavedPhotosAlbum saves only 5 image out of 10. Why?

In my case as well, the error was: "Write busy" - this seems to be an issue related to device speed. There is probably some solution that involves manually handling threading or similar - but, inspired by Tommy's answer below, I serialized the saving of images, and that works around the problem.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Situation:

I'm trying to save a large-ish collection of images to the camera roll using a for-loop (number of images depends on user input - may be 1, 2, 3, or theoretically hundreds). Images are pointed to by an NSSet (though I could just as easily do an NSArray), and the NSSet is set to nil after the for-loop completes.

I'm using UIImageWriteToSavedPhotosAlbum() to save out the images on a detached thread (using NSThread's detachNewThreadSelector:toTarget:withObject: class method), and starting a UIActivityIndicator spinner on the main thread.

Problem:

When I attempt to save out more than ~5, any image after the ~5th will output this error in the log:

*** -[NSKeyedUnarchiver initForReadingWithData:]: data is NULL

For example, let's say I exported 9 images. The for-loop will run through all 9 images (confirmed by NSLogging), but I'll get around 4 iterations of the error above (and only 5 images saved to the camera roll).

If I add a breakpoint in the loop and wait a second or two in between each iteration, however, they are all saved correctly without complaint. So..

Theory:

Based on my logs and observations, UIImageWriteToSavedPhotosAlbum() is clearly running asynchronously and is somehow 'too slow' to keep up with my application.

Is there a simple way to force it to run synchronously (ideally on the main thread)? I've been experimenting with adding reference counts to the images I'm trying to save out, but (1) this feels hacky, and (2) I haven't solved the problem regardless.

Any advice would be great. Thanks!

解决方案

If you're desperate not to write multiple images at once then you could use UIImageWriteToSavedPhotosAlbum's completion target and selector to implement a form of tail recursion. Something like:

- (void)writeSetToSavedPhotosAlbum:(NSMutableSet *)images
{
    if(![images count]) return;

    UIImage *imageToSave = [[[images anyObject] retain] autorelease];
    [images removeObject:imageToSave];
    NSLog(@"I shall now write image %@", imageToSave);

    UIImageWriteToSavedPhotosAlbum(
            imageToSave,
            self,
            @selector(writeSetToSavedPhotosAlbum:),
            images);
}

EDIT: it may also be worth seeing whether you get the same results with ALAssetsLibrary's -writeImageToSavedPhotosAlbum:orientation:completionBlock:, which takes a block for completion so is even more straightforward to work with.

这篇关于Objective-C:UIImageWriteToSavedPhotosAlbum()+ asynchronous = problems的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆