writeImageToSavedPhotosAlbum

writeImageToSavedPhotosAlbum

我正在使用信号量等待异步任务完成,但是在以下情况下我不为什么不等待,请告诉我我在哪里做错

NSLog(@"start async task");

dispatch_semaphore_t sema =  dispatch_semaphore_create(0);

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

    UIImage * image = [UIImage imageNamed:@"image.png"];

    [assetLibrary writeImageToSavedPhotosAlbum:image.CGImage
                                   orientation:ALAssetOrientationUp
                               completionBlock:^(NSURL *assetURL, NSError *error) {

                           NSLog(@"waiting for block to complete");
    }];

    dispatch_semaphore_signal(sema);
});

dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);

NSLog(@"finished");

i am getting following output -

start async task ---> finished ----> waiting for block to complete

最佳答案

如blazejmar的注释中所述,您的代码无法正常工作有两个原因:

首先:将文件写入资产库后,您的dispatch_semaphore_signal(sema);必须在完成调用中

第二个(也是更重要的):您正在阻塞主线程,但是ALAssetsLibrary需要它来完成映像的写入。

我建议您重构代码并使用其他设计模式,避免阻塞线程。
但是,如果您想要一个“简单,快速”的解决方案,只需将所有代码放到另一个调度中(并按照我的解释移动调度信号)。注意:在此代码中,我添加了一些NSLog调用以打印当前线程,稍后将解释原因

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

    NSLog(@"Thread id is %i", (int)pthread_self());

    ALAssetsLibrary *assetLibrary = [[ALAssetsLibrary alloc]init];

    NSLog(@"start async task");

    dispatch_semaphore_t sema =  dispatch_semaphore_create(0);

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        NSLog(@"Thread id is %i", (int)pthread_self());

        UIImage * image = [UIImage imageNamed:@"image.png"];

        [assetLibrary writeImageToSavedPhotosAlbum:image.CGImage
                                       orientation:ALAssetOrientationUp
                                   completionBlock:^(NSURL *assetURL, NSError *error) {

                                       NSLog(@"waiting for block to complete");

                                       dispatch_semaphore_signal(sema);
                                   }];



    });

    dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);

    NSLog(@"finished");


});


这将工作并打印

2014-07-22 08:49:24.488 Asset[66697:1139580] start async task
2014-07-22 08:49:27.709 Asset[66697:1139582] waiting for block to complete
2014-07-22 08:49:27.710 Asset[66697:1139580] finished


关于ALAssetsLibrary对主线程的使用:
我在文档中找不到它,但是您可以轻松地找到执行以下操作的系统调用使用了哪个线程(也许有人有一个更简单的方法):


如上所述,将NSLog调用放入您的代码中。
objc_msgSend上使用以下表达式创建一个符号断点:expr -- (void)printf("[%s, %s] - Thread: %i\n",(char *) object_getClassName(*(long*)($esp+4)), (char *) *(long *)($esp+8), (int) pthread_self())。这将打印所有带有其调用线程的方法调用
[assetLibrary writeImageToSavedPhotosAlbum]之后立即启用断点


就我而言:

2014-07-22 08:42:59.892 Asset [66411:1135166]线程ID为84767144 2014-07-22 08:42:59.893 Asset [66411:1135251]线程ID为-1341575168 2014-07-22 08:42:59.893 Asset [66411:1135252]线程ID为-1341042688
[assetLibrary writeImageToSavedPhotosAlbum]之后立即开始记录

[nil,CGImage]-线程:-1341042688
[OS_dispatch_semaphore,保留]-线程:-1341042688
[ALAssetsLibrary,writeImageToSavedPhotosAlbum:orientation:completionBlock:]-线程:-1341042688
[CFPrefsDirectSource,createRequestNewContentMessageForDaemon:]-线程:84767144
因此,如果您阻塞主线程,您的代码将在该调用时阻塞。

关于ios - ios-信号量不等待ALAssetsLibrary writeImageToSavedPhotosAlbum方法完成,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/24864574/

10-10 04:53