2017-08-23 7 views
1

私はシリアルDispatchQueueを使用してPHAssetsのセットを読み取り、それをリモートホストに1つずつアップロードしています。コールバックはどのキューで実行されますか?

コードではPHAsset.fetchAssets()を使用し、次にenumerateObjects内でqueue.async { .. }を使用してキューにタスクを追加します。タスク内では、PHImageManager.default().requestImageDataを使用しています。これは、アセットの内容を読み取り、クロージャを実行してDataとして返します。

ので、キューに入れられたタスクの各々の中に終わるコードは次のようになります。私は実行している

let queue = DispatchQueue(
    label: "com.myapp.asset_upload_queue", 
    qos: .background 
) 

問題

self.queue.async { 
    PHImageManager.default().requestImageData(
    for: asset, 
    options: self.imageRequestOptions()) { (data: Data?, dataUTI: String?, orientation: UIImageOrientation, info: [AnyHashable : Any]?) in 

     print("--> Upload data: \(data?.description ?? "n/a")") 
     usleep(2000000) 

    } 
} 

マイキューは、次のように定義されていますすぐにPHImageManager.requestImageDataが返ってくるので、次のタスクはすぐにデータを読み始めます。最終結果は複数の同時アップロードで終わり、CPUは全面的に屋根を撃ちます。

コールバックPHImageManager.requestImageData take isがキュースレッドをブロックしないため、次のタスクに移動することが問題であると想定します。その次の作業はすぐにデータの読み込みを開始します。

私はのように、キューにあるコールバックの内側に何入れてみました:これはシリアルアップロードの実行を開始しますが、requestImageData呼び出しがまだ次々に実行されている、巨大な負担をかけるどの

self.queue.async { 
    PHImageManager.default().requestImageData(
    for: asset, 
    options: self.imageRequestOptions()) { (data: Data?, dataUTI: String?, orientation: UIImageOrientation, info: [AnyHashable : Any]?) in 

     self.queue.async { 
      print("--> Upload data: \(data?.description ?? "n/a")") 
      usleep(2000000) 
     } 

    } 
} 

CPU上で実行します。

質問:

前回のアップロードが完了するとrequestImageDataのみ実行されますように私は流れを制御する方法を?

他のもの、私が試した

私の最初のアプローチは伝えrequestContentEditingInputWithOptionsを使用して行うことができget an asset path directly from the Photos frameworkを、試してみてすることでした。しかし、私はそれを実際のデバイスではなくシミュレータ上で動作させることしかできませんでした。

答えて

2

セマフォを試すことができます。キュー呼び出しの前にセマフォを作成し、キュー呼び出し後にセマフォに待機を追加し、キュー実行中のコードの最後にセマフォを通知します。

関連する問題