Я отправляю веб-запрос в API Google Мест на карте, чтобы выбрать близлежащие места на основе определенной координаты, а затем запускаю задачу для получения фотографии этих мест.
Я могу успешно получить сведения о местечерез первое задание, и в то время как второе задание по извлечению фотографии выполняется, его блок завершения никогда не вводится, что приводит к отсутствию фотографии, поскольку я наблюдал размещение точек останова.
urlString правильный, мой apiKey с тех пор работает правильнопервая задача возвращает правильный ответ, и у меня есть ссылка на фотографию того места, где можно выполнить веб-запрос.Любое руководство будет оценено, поскольку я, по общему признанию, потеряно - может предоставить более подробную информацию, если это необходимо.
Ниже приведены сетевые вызовы, адаптированные из руководства Рэя Вендерлиха .
typealias PlacesCompletion = ([Place]) -> Void
typealias PhotoCompletion = (UIImage?) -> Void
class DataProvider {
private var photoCache: [String: UIImage] = [:]
private var placesTask: URLSessionDataTask?
private var session: URLSession {
return URLSession.shared
}
//FIRST WEB REQUEST
func fetchPlacesNearCoordinate(_ coordinate: CLLocationCoordinate2D, radius: Double, types: [String], completion: @escaping PlacesCompletion) -> Void {
var urlString = "https://maps.googleapis.com/maps/api/place/nearbysearch/json?location=\(coordinate.latitude),\(coordinate.longitude)&radius=\(radius)&rankby=prominence&sensor=true&key=\(googleApiKey)"
let typesString = "restaurant"
urlString += "&type=\(typesString)"
urlString = urlString.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed) ?? urlString
guard let url = URL(string: urlString) else {
completion([])
return
}
if let task = placesTask, task.taskIdentifier > 0 && task.state == .running {
task.cancel()
}
DispatchQueue.main.async {
UIApplication.shared.isNetworkActivityIndicatorVisible = true
}
placesTask = session.dataTask(with: url) { data, response, error in
var placesArray: [Place] = []
defer {
DispatchQueue.main.async {
UIApplication.shared.isNetworkActivityIndicatorVisible = false
completion(placesArray)
}
}
guard let data = data,
let json = try? JSON(data: data, options: .mutableContainers),
let results = json["results"].arrayObject as? [[String: Any]] else {
return
}
results.forEach {
let place = Place(dictionary: $0, acceptedTypes: types)
placesArray.append(place)
if let reference = place.photoReference {
//SECOND WEB REQUEST CALL
self.fetchPhotoFromReference(reference) { image in
place.photo = image
}
}
}
}
placesTask?.resume()
}
//SECOND WEB REQUEST
func fetchPhotoFromReference(_ reference: String, completion: @escaping PhotoCompletion) -> Void {
if let photo = photoCache[reference] {
completion(photo)
} else {
let urlString = "https://maps.googleapis.com/maps/api/place/photo?maxwidth=200&maxheight=200&photoreference=\(reference)&key=\(googleApiKey)"
guard let url = URL(string: urlString) else {
completion(nil)
return
}
DispatchQueue.main.async {
UIApplication.shared.isNetworkActivityIndicatorVisible = true
}
session.downloadTask(with: url) { url, response, error in
var downloadedPhoto: UIImage? = nil
defer {
DispatchQueue.main.async {
UIApplication.shared.isNetworkActivityIndicatorVisible = false
completion(downloadedPhoto)
}
}
guard let url = url else {
return
}
guard let imageData = try? Data(contentsOf: url) else {
return
}
downloadedPhoto = UIImage(data: imageData)
self.photoCache[reference] = downloadedPhoto
}
.resume()
}
}
}
.