2016-08-22 6 views
-1

У меня есть следующая функция, которая возвращает [CIImage] для моей цели - отображение некоторых метаданных фотографий в таблицеView.Почему приложение заблокировано семафором?

func getCIImages() -> [CIImage] { 
    var images = [CIImage]() 
    let assets = PHAsset.fetchAssetsWithMediaType(.Image, options: nil) 

    for i in 0..<assets.count { 
     guard let asset = assets[i] as? PHAsset else {fatalError("Cannot cast as PHAsset")} 
     let semaphore = dispatch_semaphore_create(0) 

     asset.requestContentEditingInputWithOptions(nil) { contentEditingInput, _ in 
      //Get full image 
      guard let url = contentEditingInput?.fullSizeImageURL else {return} 
      guard let inputImage = CIImage(contentsOfURL: url) else {return} 
      images.append(inputImage) 
      dispatch_semaphore_signal(semaphore) 
     } 
     dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER) 
    } 
    return images 
} 

но это stucks в семафоре ждут и не идут дальше. Я прошел много учебников, но другие варианты GCD не работают. Я думаю, это из-за симулятора, я не знаю, не могу проверить на реальном устройстве. Пожалуйста помоги.

+2

Почему вы вынуждаете квазисинхронный запрос вообще? – vadian

+0

@vadian, потому что я хочу отображать некоторые метаданные 'CIImages' в' tableView', и это можно сделать синхронно с одним вызовом 'tableView.reloadData()'. –

ответ

5

охранники внутри requestContentEditingInputWithOptions замыкание обратного вызова предотвращает передачу сигнала в семафор. В таких случаях (когда вам нужны действия по очистке), полезно использовать defer. В вашем случае:

asset.requestContentEditingInputWithOptions(nil) { contentEditingInput, _ in 
    defer { dispatch_semaphore_signal(semaphore) } 

    //Get full image 
    guard let url = contentEditingInput?.fullSizeImageURL else {return} 
    guard let inputImage = CIImage(contentsOfURL: url) else {return} 
    images.append(inputImage) 
} 

UPDATE

Помимо очистки жука есть еще один. Завершение закрытия requestContentEditingInputWithOptions вызвано основной нитью. Это означает, что если вы блокируете основной поток с помощью семафора: завершение закрытия также блокируется. Чтобы исправить проблему с семафором, вам нужно позвонить getCIImages на другой поток, кроме основного.

В любом случае создание синхронных асинхронных операций является неправильным. Вы должны думать о другом подходе.

+2

Именно тот случай, почему 'defer' был введен! – Sulthan

+0

Ни один из символов 'guard' не вызывает' else'. Этот код производит такое же поведение, как мой код - программа freezes –

+0

Обновлен мой ответ – Silmaril

 Смежные вопросы

  • Нет связанных вопросов^_^