2017-11-23 6 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

AVAssetExportSessionやAVResourceLoaderDelegateのような非同期APIを使用している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

関連する問題