2017-09-02 45 views
0

我目前有一個數組迭代通過價值圖像路徑,並希望異步檢索這些圖像在for循環內的第一個。我試過使用兩個分派組,但完成處理程序總是在檢索圖像之前返回。如何使用DispatchGroup與兩個循環

static func getAllEntriesWithDisplayModel(completion: @escaping (_ models: [EntryDisplayModel]) ->()) ->(){ 
     let entries = Array(realm.objects(Entry.self)).reversed() 
     var displayModels: [EntryDisplayModel] = [] 

    let options = PHFetchOptions() 
    let entriesGroup = DispatchGroup() 

    entries.forEach{ 

     entriesGroup.enter() 
     var model = EntryDisplayModel(entry: $0) 

     let paths: [String] = $0.imagePaths.flatMap{en in 
      en.path 
     } 
     let assets = PHAsset.fetchAssets(withLocalIdentifiers: paths, options: options) 
     assets.enumerateObjects({ (object, count, stop) in 
      model.assets?.append(object) 
     }) 

     let assetsGroup = DispatchGroup() 

     let requestOptions = PHImageRequestOptions() 
     requestOptions.resizeMode = PHImageRequestOptionsResizeMode.exact 
     requestOptions.deliveryMode = PHImageRequestOptionsDeliveryMode.highQualityFormat 
     requestOptions.isSynchronous = true 

     var images: [UIImage]? = [] 

     model.assets?.forEach{ 
      assetsGroup.enter() 

      // Fetch images using local paths from images save 
      PHImageManager.default().requestImage(for: $0, targetSize: PHImageManagerMaximumSize, contentMode: PHImageContentMode.default, options: requestOptions, resultHandler: { (image, info) in 
       guard let img = image else { 
        assetsGroup.leave() 
        return 
       } 
       images?.append(img) 
       assetsGroup.leave() 
      }) 
     } 
     assetsGroup.notify(queue: .main, execute: { 
      model.images = images 
      print("FETCHED \(images?.count ?? 0) IMAGES") 
      print("DISPLAY MODEL CREATED ") 
      displayModels.append(model) 
     }) 

    } 
    entriesGroup.leave() 
    //Returns too early 
    entriesGroup.notify(queue: .main, execute: { 
     print(" FINISHED CREATING DISPLAY MODELS") 
     completion(displayModels) 
    }) 
} 
+0

哪裏是'entriesGroup.leave()'?使用你的代碼,_too early_ completion處理程序永遠不會被調用。 – OOPer

+0

在循環結束後,它纔是正確的。抱歉忘了包括 –

回答

1

看起來你的代碼太早了entriesGroup.leave()。你知道嗎,你的assetsGroup.leave()被稱爲在完成處理時,forEach循環結束後不對:

static func getAllEntriesWithDisplayModel(completion: @escaping (_ models: [EntryDisplayModel]) ->()) ->(){ 
    //... 

    entries.forEach{ 

     entriesGroup.enter() 

     //... 

     let assetsGroup = DispatchGroup() 

     //... 

     model.assets?.forEach {_ in 
      assetsGroup.enter() 

      // Fetch images using local paths from images save 
      PHImageManager.default().requestImage(for: $0, targetSize: PHImageManagerMaximumSize, contentMode: PHImageContentMode.default, options: requestOptions, resultHandler: { (image, info) in 
       //... 
       assetsGroup.leave() 
      } 
     } 
     assetsGroup.notify(queue: .main, execute: { 
      model.images = images 
      print("FETCHED \(images?.count ?? 0) IMAGES") 
      print("DISPLAY MODEL CREATED ") 
      displayModels.append(model) 
      entriesGroup.leave() //<-`entriesGroup.leave()` needs to be called after all processing for the entry is finished. 
     }) 

    } 
    //entriesGroup.leave() //<-It is too early to call `entriesGroup.leave()` here 
    entriesGroup.notify(queue: .main, execute: { 
     print(" FINISHED CREATING DISPLAY MODELS") 
     completion(displayModels) 
    }) 
}