#ios #arrays #swift
#iOS #массивы #swift
Вопрос:
Я использую API для получения координат широты и долготы и размещения их на карте с названием места, которому оно соответствует. Я могу указать широтные и длинные координаты одного места, но я не слишком уверен, как добавить их все на карту. Я не могу понять, как это сделать. Я пытался использовать для этого цикл for, но я слишком уверен в том, как я бы это реализовал. Это то, что у меня есть до сих пор:
func getData() {
let url = "https://www.givefood.org.uk/api/2/foodbanks/"
let task = URLSession.shared.dataTask(with: URL(string: url)!, completionHandler: { [self] data, response, error in
guard let data = data, error == nil else {
print("Wrong")
return
}
var result: [Info]?
do {
result = try JSONDecoder().decode([Info].self, from: data)
}
catch {
print("Failed to convert: (error.localizedDescription)")
}
guard let json = result else {
return
}
for each in json {
var each = 0
each = 1
let comp = json[each].lat_lng?.components(separatedBy: ",")
let latString = comp![each]
let lonString = comp![each]
let lat = Double(latString)
let lon = Double(lonString)
let locationPin: CLLocationCoordinate2D = CLLocationCoordinate2DMake(lat!, lon!)
let location: CLLocationCoordinate2D = CLLocationCoordinate2DMake(51.55573, -0.108312)
let region = MKCoordinateRegion.init(center: location, latitudinalMeters: regionInMetres, longitudinalMeters: regionInMetres)
mapView.setRegion(region, animated: true)
let myAn1 = MapPin(title: json[each].name!, locationName: json[each].name!, coordinate: locationPin)
mapView.addAnnotations([myAn1])
}
})
task.resume()
}
Ответ №1:
Ваш цикл неправильный, each
после for
— один Info
элемент. Int
Индекс each
не имеет смысла, и вы устанавливаете его на каждой итерации равным нулю, поэтому вы всегда получаете одну и ту же координату (с индексом 1).
Прежде всего объявить name
и lat_lng
как необязательный. Все записи содержат оба поля.
struct Info : Decodable {
let lat_lng : String
let name : String
}
Во-вторых, из соображений удобства расширьте CLLocationCoordinate2D
, чтобы создать координату из строки
extension CLLocationCoordinate2D {
init?(string: String) {
let comp = string.components(separatedBy: ",")
guard comp.count == 2, let lat = Double(comp[0]), let lon = Double(comp[1]) else { return nil }
self.init(latitude: lat, longitude: lon )
}
}
В-третьих, поместите весь хороший код в область do
видимости вместо того, чтобы иметь дело с опциями, и установите регион один раз перед циклом
func getData() {
let url = "https://www.givefood.org.uk/api/2/foodbanks/"
let task = URLSession.shared.dataTask(with: URL(string: url)!, completionHandler: { [self] data, response, error in
if let error = error { print(error); return }
do {
let result = try JSONDecoder().decode([Info].self, from: data!)
let location = CLLocationCoordinate2D(latitude: 51.55573, longitude: -0.108312)
let region = MKCoordinateRegion.init(center: location, latitudinalMeters: regionInMetres, longitudinalMeters: regionInMetres)
mapView.setRegion(region, animated: true)
var pins = [MapPin]()
for info in result {
if let coordinate = CLLocationCoordinate2D(string: info.lat_lng) {
pins.append(MapPin(title: info.name, locationName: info.name, coordinate: coordinate))
}
}
DispatchQueue.main.async {
self.mapView.addAnnotations(pins)
}
}
catch {
print("Failed to convert: (error)")
}
})
task.resume()
}