2015-11-23 2 views
0

У меня есть следующий метод, когда я хотел бы вернуть movieDestinationUrl, если SessionStatus завершен, однако я продолжаю получать эту ошибку Unexpected non-void return value in void function. Что я делаю не так?Возвращаемое значение внутри асинхронного завершенияHandler

func createVideo() -> NSURL { 

    // create new file to receive data 
    let docsDir: AnyObject = documentsPath 
    let movieFilePath = docsDir.stringByAppendingPathComponent("result.mov") 
    let movieDestinationUrl = NSURL(fileURLWithPath: movieFilePath) 
    _ = try? NSFileManager().removeItemAtURL(movieDestinationUrl) 

    // use AVAssetExportSession to export video 
    let assetExport = AVAssetExportSession(asset: composition, presetName:AVAssetExportPresetHighestQuality) 
    assetExport!.outputFileType = AVFileTypeQuickTimeMovie 
    assetExport!.outputURL = movieDestinationUrl 
    assetExport?.videoComposition = layercomposition 
    assetExport!.exportAsynchronouslyWithCompletionHandler({ 
     switch assetExport!.status{ 
     case AVAssetExportSessionStatus.Failed: 
      print("failed \(assetExport!.error)") 
     case AVAssetExportSessionStatus.Cancelled: 
      print("cancelled \(assetExport!.error)") 
     default: 
      print("Movie complete") 


      // save to photoalbum 
      return movieDestinationUrl 

     } 
    }) 

} 

ответ

0

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

var movieDestinationUrlGetter: NSURL? { 
    didSet { 
     //save to photoalbum 
    } 
} 

func createVideo() -> NSURL { 
. 
. 

assetExport!.exportAsynchronouslyWithCompletionHandler({ 
    switch assetExport!.status{ 
    case AVAssetExportSessionStatus.Failed: 
     print("failed \(assetExport!.error)") 
    case AVAssetExportSessionStatus.Cancelled: 
     print("cancelled \(assetExport!.error)") 
    default: 
     dispatch_async(dispatch_get_main_queue()) { 
      print("Movie complete") 
      movieDestinationUrlSGetter = movieDestinationUrl 
     } 
    } 
}) 
0

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

func createVideo() { 

    // create new file to receive data 
    let docsDir: AnyObject = documentsPath 
    let movieFilePath = docsDir.stringByAppendingPathComponent("result.mov") 
    let movieDestinationUrl = NSURL(fileURLWithPath: movieFilePath) 
    _ = try? NSFileManager().removeItemAtURL(movieDestinationUrl) 

    // use AVAssetExportSession to export video 
    let assetExport = AVAssetExportSession(asset: composition, presetName:AVAssetExportPresetHighestQuality) 
    assetExport!.outputFileType = AVFileTypeQuickTimeMovie 
    assetExport!.outputURL = movieDestinationUrl 
    assetExport?.videoComposition = layercomposition 
    assetExport!.exportAsynchronouslyWithCompletionHandler({ 
     switch assetExport!.status{ 
     case AVAssetExportSessionStatus.Failed: 
      print("failed \(assetExport!.error)") 
     case AVAssetExportSessionStatus.Cancelled: 
      print("cancelled \(assetExport!.error)") 
     case AVAssetExportSessionStatus.Completed: { 
      print("Movie complete") 

      self.onExportComplete(movieDestinationUrl) // a method where you notify self that the export is successfully complete 
     } 

     default: { 
      print("Export did not complete") 
     } 
    }) 
} 

Обратите внимание, что теперь этот метод возвращает void, так как нет ничего, чтобы вернуться до тех пор, пока не будет сделан экспорт.

Также обратите внимание, что вы не покрывали все возможные коды состояния, поэтому случай по умолчанию также может означать, что полное не закончилось успешно r причин. Используйте статус «Завершено», чтобы убедиться, что он завершен.

0

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

Один из подходов состоит в том, чтобы использовать уведомление и включать URL-адрес в качестве части данных, прикрепленных к уведомлению.

+0

Как это могло бы выглядеть? –

+0

Посмотрите на документы для 'NSNotificationCenter'. Если после этого это не ясно, сообщите мне, какая часть вас смущает. –

1

Синхронный: вам нужен молоток. Вы посылаете кого-то, чтобы забрать молоток из вашего инструментария, вернуться с ним и передать молоток. Тем временем вы ждёте возвращения этого человека. Очень просто, очень неэффективно, потому что вы все время ждёте других.

Асинхронный: вам нужен молоток. Вы отправляете кого-то, чтобы забрать молоток из панели инструментов. Но вы не ждете возвращения молота, потому что у вас есть другие дела. Когда человек возвращается с молотом, они помещают его в место, обозначенное «молот здесь!». и поставьте записку «молоток готов» на ваш стопку заметок. Как только вы закончите то, что делаете, вы увидите записку, уберите ее и заберите молоток.

Так работают асинхронные вызовы. Они заканчиваются, они откладывают результаты где-то там, где их можно найти, и обычно уведомляют вас, вызывая блок кода, который вы им дали. (это «completeHandler»).

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