我看了很多使用调度组的示例,但似乎无法使它正常工作。
我正在为自己的项目使用Google地图,并在附近的商家处放置了标记。单击标记后,我想显示另一个具有该位置图像的视图控制器。
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)
}
})
}
答案 0 :(得分: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
}