2017-11-23 4 views
0

일련의 비디오를 다운로드하려면 OperationOperationQueue을 사용하고 있습니다. 내 다운로드는 Operation입니다.작업 내에서 큐에 액세스

import UIKit 
import AVFoundation 

class VideoDownloader: Operation { 
    let videoRecord: VideoRecord 

    init(videoRecord: VideoRecord) { 
     self.videoRecord = videoRecord 
    } 

    override func main() { 
     if isCancelled { 
      return 
     } 

     let asset = AVURLAsset(url: videoRecord.url) 
     asset.resourceLoader.setDelegate(self, queue: DispatchQueue.main) 

     let exporter = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetHighestQuality) 
     let filename = "\(videoRecord.id).mp4" 

     let documentsDirectory = FileManager.default.urls(for: FileManager.SearchPathDirectory.documentDirectory, in: FileManager.SearchPathDomainMask.userDomainMask).last! 
     let outputURL = documentsDirectory.appendingPathComponent(filename) 

     exporter?.outputURL = outputURL 
     exporter?.outputFileType = .mp4 

     exporter?.exportAsynchronously { 
      if let error = exporter?.error { 
       print(error) 
      } else { 
       print(outputURL) 
      } 
     } 
    } 
} 

extension VideoDownloader: AVAssetResourceLoaderDelegate { 

} 

이 작동합니다. 그러나 나는 아래 라인에 대해 우려하고있다.

asset.resourceLoader.setDelegate(self, queue: DispatchQueue.main) 

현재 주 스레드에서 대리인을 설정하고 있습니다. 이것은 백그라운드 스레드에서 실행되기 때문에 올바른 것으로 생각하지 않습니다. 나는 내가 틀린다면 나에게 정정 해주세요.

작업을 현재 실행중인 대기열에 대기열을 설정할 수 있다면 가장 좋을 것이라고 생각했습니다. 하지만 작업 클래스에서 대기열에 어떻게 액세스 할 수 있습니까?

+0

원격 URL에서 비디오 파일을 다운로드 하시겠습니까? – SeanLintern88

+0

@ SeanLintern88 네, 그렇습니다. – Isuru

+0

TBH,이 같은 접근 방식을 본적이 없으며 일반적으로 UrlSessionDataTask를 사용하여 비디오를 다운로드 할 것입니다. AVAssetExportSession이 백그라운드에서 작동하지 않는다는 것을 알고 있습니다. 누군가가 앱을 배경으로 설정하면 실패합니다. – SeanLintern88

답변

0

비동기 API (예 : AVAssetExportSession 및 AVResourceLoaderDelegate)를 사용중인 main() 내부에서 비동기 작업을 구현해야합니다 (Apple은 이에 대한 문서를 가지고 있습니다). 내부 속성의 상태를 변경하고 willChangeValueForKey 및 didChangeValueForKey를 호출하여 비동기 작업이 완료 될 때 OperationQueue에 알릴 수 있도록해야합니다. 이 작업을 수행하지 않으면 OperationQueue는 main() 메서드가 반환 되 자마자 작업이 완료 될 것이라고 믿습니다. OperationQueue는 대기열에서 작업을 제거하고 maxConcurrentOperations는 존중되지 않습니다. 왜냐하면 실제로 작업이 후드에서 계속 실행되기 때문입니다.

차단하지 않고 다양한 스레드에서 실행할 수있는 비동기 API를 사용하고 있기 때문에 자신의 백그라운드 대기열을 만들거나 AVResourceLoaderDelegate의 기존 글로벌 대기열을 사용하는 것이 좋습니다. OperationQueue의 내부 큐를 그대로 유지하면 간단한 동기화 계층으로 작동합니다.

+0

응답 해 주셔서 감사합니다. 비동기식 작업을 살펴본 후 [이 기사] (http://swiftgazelle.com/2016/03/asynchronous-nsoperation-why-and-how/#comment-6472)를 보았습니다. 그래서 나는 그에 맞게 수업을 수정했다. 다음은 업데이트 된 [버전]입니다 (https://pastebin.com/BThygXwL). 그런 뜻 이니? – Isuru

관련 문제