Рассмотрим что-то более гибкое в форме структуры, соответствующей Codable:
struct Place: Codable {
let latitiude: Double
let longitude: Double
let name: String
}
var myPlaces = [
Place(latitiude: 47.828640, longitude: 16.609410, name: "Place A"),
Place(latitiude: 47.737929, longitude: 16.511681, name: "Place B"),
Place(latitiude: 48.065218, longitude: 16.924627, name: "Place C"),
Place(latitiude: 48.140537, longitude: 16.824681, name: "Place D")
]
// Saving places:
func save(places: [Place]) throws {
do {
let encoded = try PropertyListEncoder().encode(places)
let url = getDocumentsDirectory().appendingPathComponent("places.json")
try encoded.write(to: url)
}
}
// Loading places:
func loadPlaces() -> [Place]? {
let url = getDocumentsDirectory().appendingPathComponent("places.json")
guard let data = try? Data(contentsOf: url) else { return nil }
return try? PropertyListDecoder().decode([Place].self, from: data)
}
// Helper from https://www.hackingwithswift.com/example-code/system/how-to-find-the-users-documents-directory
func getDocumentsDirectory() -> URL {
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
let documentsDirectory = paths[0]
return documentsDirectory
}
Использование в таком случае:
// To save:
do {
try save(places: myPlaces)
} catch {
// Couldn't save for some reason - look into the thrown exception
}
// To load, allowing for the initial condition that there are
// not yet any saved places to be loaded
myPlaces = loadPlaces() ?? []
Заполнение вашей карты становится примерно таким:
// Turn every `Place` into an MKPointAnnotation
myPlaces.map { place -> MKPointAnnotation in
let annotation = MKPointAnnotation()
annotation.coordinate = CLLocationCoordinate2D(latitude: place.latitiude,
longitude: place.longitude)
annotation.subtitle = place.name
return annotation
}
// ... and add them to our map
.forEach(map.addAnnotation)
Подсказка: Не используйте имена переменных с начальными заглавными буквами.Это делает их похожими на имена типов и приведет к путанице в будущем (например, @IBOutlet var map: MKMapView!
будет предпочтительным).
Подсказка: Если вы когда-нибудь обнаружите, что вручную отслеживаете индекс массиваЭто хороший признак, который вы, вероятно, должны учитывать forEach
или for x in y
или map
, особенно если значение only используется в качестве индекса,Если само значение имеет значение (например, title = "This is section \(idx)"
), тогда .enumerated
- ваш друг.
Подсказка: Если вы хотите, чтобы ваши сохраненные данные были более читабельными / редактируемыми, или, возможно,быть доставленным веб-службой, рассмотрите вместо этого JSONEncoder / JSONDecoder.