Как я могу использовать DispatchGroup для поиска фотографий и хранения в массиве UIImage - PullRequest
0 голосов
/ 05 сентября 2018

Я рассмотрел довольно много примеров использования группы рассылки, но, похоже, не могу заставить ее работать.

Я использую Google Maps для своего проекта и установил маркеры на близлежащих предприятиях. При нажатии на маркер, я хочу показать другой контроллер представления, который имеет изображения этого места.

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, который я добавляю в свой массив. Из того, что я понимаю, поиск фотографий и загрузка фотографий - это асинхронные вызовы. Как я могу использовать 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)

        }
    })
}

1 Ответ

0 голосов
/ 05 сентября 2018

Ваше использование 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
}
...