ios编程:使用线程将多个图像添加到库中

时间:2013-12-18 16:05:34

标签: ios multithreading image

在Xcode中,当我尝试将超过5张图片添加到我的库时,它会给我以下错误:

Error Domain=ALAssetsLibraryErrorDomain Code=-3301 "Write busy" UserInfo=0xa706aa0 {NSLocalizedRecoverySuggestion=Try to write again, NSLocalizedFailureReason=There was a problem writing this asset because the writing resources are busy., NSLocalizedDescription=Write busy, NSUnderlyingError=0xa770110 "Write busy"}

为了解决这个问题,我发现线程可以解决我的问题。文档说明我可以使用POSIX线程或NSThreads。当我尝试使用POSIX线程时,我将我的线程设置为可连接,并且我正在创建一个void *函数:

void * myFunc (void * image)
{
       UIImageWriteToSavedPhotosAlbum((__bridge UIImage *)(image),self,nil,nil);
       pthread_exit(NULL);
       return NULL;
}

我也在等待线程结束。但是仍然只写了5张图像。

我尝试过使用NSThreads并做了:

[self performSelectorOnMainThread:@selector(myFunc:) withObject:image waitUntilDone:YES];

但它仍然不起作用。

我的问题有答案吗?这对我的工作至关重要。

感谢。

编辑:

也尝试了dispatch_async。这是错的吗?

dispatch_queue_t myQueue = dispatch_queue_create("com.cropr.myqueue", 0);

for (UIImage * image in images) {

        dispatch_async(myQueue, ^{

            [self.library saveImage:image toAlbum:@"Cropr" withCompletionBlock:^(NSError *error) {
                if (error!=nil) {
                    NSLog(@"Big error: %@", [error description]);
                }
            }];

        });

    }

我需要添加什么?

3 个答案:

答案 0 :(得分:3)

您可以尝试随后编写所有图像,而不是同时。以下代码使用ALAssetsLibrary,并实现了一个“异步循环”,它在 sequence 中调用了许多异步方法。

typedef void (^completion_t)(id result);

- (void) writeImages:(NSMutableArray*)images 
          completion:(completion_t)completionHandler {
    if ([images count] == 0) {
        if (completionHandler) {
            // Signal completion to the call-site. Use an appropriate result,
            // instead of @"finished" possibly pass an array of URLs and NSErrors 
            // generated below  in "handle URL or error".
            completionHandler(@"finished");  
        }
        return;
    }

    UIImage* image = [images firstObject];
    [images removeObjectAtIndex:0];

    [self.assetsLibrary writeImageToSavedPhotosAlbum:image.CGImage 
                                         orientation:ALAssetOrientationUp
                                     completionBlock:^(NSURL *assetURL, NSError *error)
    {
        // Caution: check the execution context - it may be any thread,
        // possibly use dispatch_async to dispatch to the main thread or
        // any other queue.

        // handle URL or error
        ...
        // next image:
        [self writeImages:images completion:completionHandler];
    }];
}

用法:

[foo writeImages:[foo.images mutableCopy] completion:^(id result){
    // Caution: check the execution context - it may be any thread
    NSLog(@"Result: %@", result);   
}];

答案 1 :(得分:1)

我建议您使用NSOperationQueue并使用maxConcurrentOperationCount的值。这样,您就可以控制对库的同时写入次数,而不是压倒它。

如果你使用线程,甚至是GCD,你需要自己实现这个逻辑。更多代码 - >更有可能引入错误。

答案 2 :(得分:0)

Dispatch_async可以在后台执行,因此我将for{}和函数调用放在dispatch_async正文中 因此,将for放在dispatch async内会将您的图像存储在相册中,就像运行for一样。但是在单独的线程上。

    dispatch_queue_t myQueue = dispatch_queue_create("com.cropr.myqueue", 0);
    dispatch_async(myQueue, ^{

      for (UIImage * image in images) 
          UIImageWriteToSavedPhotosAlbum((__bridge UIImage *)(image),self,nil,nil);
    });

}

您也可以试试这个。我认为会更好,看看它是否有效,然后添加你想要处理的错误。

此外,我认为这是您想要的答案:iOS: dispatch_async and UIImageWriteToSavedPhotosAlbum