Ожидание завершения блока writeImageToSavedPhotosAlbum от семафора

В моем приложении я открываю камеру сборщиком, и после того, как фотография была сделана, я бы хотел сохранить ее следующим способом, используя библиотеку ресурсов. Метод зависает после вызова writeImageToSavedPhotosAlbum.

Без семафоров методы работают отлично. Но чем я скучаю, чтобы получить assetURL.

+ (NSURL*)safeImageToAssetsLibrary:(UIImage *)image metadata:(NSDictionary *)metadata
{
    ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
    __block NSURL *retAssestURL = nil;

    dispatch_semaphore_t semaWaitingForSafeImage = dispatch_semaphore_create(0);
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

    // safe the image to the assests library
    NSLog(@"Safe image to asssets library...");

    dispatch_async(queue, ^{
        [library writeImageToSavedPhotosAlbum:image.CGImage metadata:metadata completionBlock:^(NSURL *assetURL, NSError *error) {

            if (error) {
                NSLog(@"Image could not be safed to the assets library: %@", error);
                retAssestURL = nil;
            }
            else {
                NSLog( @"Image safed successfully to assetURL: %@", assetURL);
                retAssestURL = assetURL;
            }

            dispatch_semaphore_signal(semaWaitingForSafeImage);
        }];
    });

    dispatch_semaphore_wait(semaWaitingForSafeImage, DISPATCH_TIME_FOREVER);

    return retAssestURL;
}

И это метод, где я называю safeImageToAssetsLibrary метод:

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
    [picker dismissViewControllerAnimated:YES completion:NULL];

    // get chosen image and add thumbnail to collection view
    NSURL *imageUrl        = info[UIImagePickerControllerReferenceURL];
    UIImage *chosenImage   = info[UIImagePickerControllerOriginalImage];

    // safe image to photo library if the camera has been used
    if (picker.sourceType == UIImagePickerControllerSourceTypeCamera) {
        imageUrl = [BaseImageHandler safeImageToAssetsLibrary:chosenImage metadata:info[UIImagePickerControllerMediaMetadata]];
    }

    // UPDATE View and Core Data here...

}

1 ответ

Решение

Не жди Никогда, никогда не делай то, что делаешь. Вы не понимаете, что такое "асинхронный". Это означает, что вам перезвонят, когда все закончится в блоке завершения. Вот где вы выполните следующий шаг.

НЕ пытайтесь вернуть значение из метода, который получает это значение в блоке асинхронного завершения.

Итак, здесь, в writeImageToSavedPhotosAlbum: блок завершения, где вы получаете retAssestURL, Так что, если есть дальнейший шаг, теперь сделайте это там, в блоке завершения. Это может включать в себя вызов другого метода или что угодно, но дело в том, что теперь все будет происходить в правильном порядке.

И, прежде всего, НЕ используйте семафоры (или другие хитрости), чтобы попытаться превратить асинхронный в синхронный. Асинхронные вещи являются асинхронными по причине. Используйте рамки, не боритесь с этим. (На самом деле, то, что вы делаете с семафорами здесь, это не просто борьба с фреймворком, а плевок в глаза.)

Другие вопросы по тегам