0

我已经看过很多使用调度组的例子,但我似乎无法让它工作。

我在我的项目中使用谷歌地图,并在附近的商家放置了标记。单击标记时,我想显示另一个具有该地点图像的视图控制器。

func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -> Bool {
  self.loadPhotosForSalonByPlaceId(placeID: poiItem.placeId)
  photoDispatchGroup.wait()
  let salonInfoViewController = self.addPullUpController() //show view controller


  salonInfoViewController.ImageCarouselView.images = self.salonImages
  salonInfoViewController.salonName.text = poiItem.name
  salonInfoViewController.salonAddress.text = poiItem.address
  salonInfoViewController.openAppointmentSlotArray = self.openAppointmentSlots

  self.isSalonInfoViewPresented = true
  return isSalonInfoViewPresented
}

这就是我的 loadPhotosForSalonByPlaceId 的样子:

func loadPhotosForSalonByPlaceId(placeID: String){

    var countToLimitToFiveImages = 0
    GMSPlacesClient.shared().lookUpPhotos(forPlaceID: placeID) { (photos, error) -> Void in

        if let error = error {
            // TODO: handle the error.
            print("Error: \(error.localizedDescription)")
        } else {
            for photoMetadata in (photos?.results)! {
                if countToLimitToFiveImages == 5 {
                    break;
                }
                self.photoDispatchGroup.enter()
                self.loadImageForMetadata(photoMetadata: photoMetadata)
                self.photoDispatchGroup.leave()
                countToLimitToFiveImages += 1
            }
        }
    }
}

我是否错误地使用了进入和离开?还是应该在lookUpPhotos 完成后通知主线程继续?因为现在,当我想显示视图控制器时,UIImages 数组是空的。

提前致谢!

下面的代码是我在 loadPhotosForSalonByPlaceId 函数中调用的代码。它将 PhotoMetaData 转换为 UIImage,我将其附加到我的数组中。据我了解,查找照片和 loadplacephoto 是异步调用。完成这两项任务后,如何使用 DispatchGroup 显示我的视图控制器。

func loadImageForMetadata(photoMetadata: GMSPlacePhotoMetadata) {
    var image = UIImage()
    GMSPlacesClient.shared().loadPlacePhoto(photoMetadata, callback: {
        (photo, error) -> Void in
        if let error = error {
            // TODO: handle the error.
            print("Error: \(error.localizedDescription)")

        } else {
            image = photo!
            self.salonImages.append(image)

        }
    })
}
4

1 回答 1

0

您当前对 DispatchGroup 的使用都是错误的。您应该enter在异步进程开始之前调用,并leave在异步进程完成时调用。并且永远不要调用wait主队列。你会想要使用notify. 同样,在这种情况下不要使用调度组。

您在这里有两个级别的异步调用。第一个是在loadImageForMetadata. 这需要重构以提供完成处理程序。第二个是loadPhotosForSalonByPlaceId其中也需要重构以提供完成处理程序。您还需要重做您如何使用调度组。

这是您的重构loadImageForMetadata

func loadImageForMetadata(photoMetadata: GMSPlacePhotoMetadata, completion: (Bool) -> Void) {
    var image = UIImage()
    GMSPlacesClient.shared().loadPlacePhoto(photoMetadata, callback: {
        (photo, error) -> Void in
        if let error = error {
            // TODO: handle the error.
            print("Error: \(error.localizedDescription)")
            completion(false)
        } else {
            image = photo!
            self.salonImages.append(image)
            completion(true)
        }
    })
}

loadPhotosForSalonByPlaceId这是使用完成处理程序和正确使用 DispatchGroup 进行的重构:

func loadPhotosForSalonByPlaceId(placeID: String, completion: (Bool) -> Void) {
    var countToLimitToFiveImages = 0
    GMSPlacesClient.shared().lookUpPhotos(forPlaceID: placeID) { (photos, error) -> Void in
        if let error = error {
            // TODO: handle the error.
            print("Error: \(error.localizedDescription)")
            completion(false)
        } else {
            let group = DispatchGroup()

            for photoMetadata in (photos?.results)! {
                if countToLimitToFiveImages == 5 {
                    break;
                }
                group.enter()
                self.loadImageForMetadata(photoMetadata: photoMetadata) { (success) in
                     if success {
                         countToLimitToFiveImages += 1
                     }
                     group.leave()
                }
            }

            group.notify(queue: DispatchQueue.global()) {
                completion(true)
            }
        }
    }
}

然后更新您的使用情况:

func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -> Bool {
    self.loadPhotosForSalonByPlaceId(placeID: poiItem.placeId) { (success) in
        if success {
            DispatchQueue.main.async {
                let salonInfoViewController = self.addPullUpController() //show view controller

                salonInfoViewController.ImageCarouselView.images = self.salonImages
                salonInfoViewController.salonName.text = poiItem.name
                salonInfoViewController.salonAddress.text = poiItem.address
                salonInfoViewController.openAppointmentSlotArray = self.openAppointmentSlots
            }
        }
    }

    self.isSalonInfoViewPresented = true
    return isSalonInfoViewPresented
}
于 2018-09-05T03:41:26.670 回答