Как использовать plist как вид хранилища в swift? - PullRequest
0 голосов
/ 08 июля 2019

Я написал приложение с представлением MapKit, и у меня есть несколько аннотаций, показанных на карте. Я использовал массивы для долготы, широты и названий мест, и это прекрасно работает. Но так как все больше и больше мест добавляется, становится очень трудно найти данные для конкретного места. Я хотел бы использовать plist для хранения данных каждого места в собственном массиве, но я не мог выяснить, как получить доступ к plist и конкретным необходимым данным.

Я только пытался создать plist, и внутри массива корневого словаря я создал массив, каждый из которых содержал Item 0 в виде строки «Название места», Item 1 в качестве Number (LatitudeNumber) и Item 2 в качестве Number (LongitudeNumber).

@IBOutlet var Map: MKMapView!

override func viewDidLoad() {
    super.viewDidLoad()

    let laditudeArray = [47.828640, 47.737929, 48.065218, 48.140537]
    let longitudeArray = [16.609410, 16.511681, 16.924627, 16.824681]
    let nameArray = ["Place A", "Place B", "Place C", "Place D"]

    var index = 0

    while index < nameArray.count {

    let places = MKPointAnnotation()
        places.coordinate = CLLocationCoordinate2D(latitude: laditudeArray[index], longitude: longitudeArray[index])
    places.subtitle = nameArray[index]

    Map.addAnnotation(places)

    index = index + 1

    }

}

Я хотел бы получить значение из элемента 0 массива в списке (который является названием места) в местах. Подзаголовок.

Ответы [ 2 ]

1 голос
/ 08 июля 2019

Вы можете использовать PropertyListEncoder и PropertyListDecoder.

. Для этого вы можете создать пользовательский тип, соответствующий Codable:

struct Place: Codable {
    let name: String
    let latitude: CLLocationDegrees
    let longitude: CLLocationDegrees
}

Затем вы можете создать свой массив следующим образом:

let places = [
    Place(name: "Place A", latitude: 47.828640, longitude: 16.609410),
    Place(name: "Place B", latitude: 47.737929, longitude: 16.511681),
    Place(name: "Place C", latitude: 48.065218, longitude: 16.924627),
    Place(name: "Place D", latitude: 48.140537, longitude: 16.824681)
]

Чтобы сохранить его в списке:

do {
    let fileURL = try FileManager.default
        .url(for: .applicationSupportDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
        .appendingPathComponent("places.plist")

    let data = try PropertyListEncoder().encode(places)
    try data.write(to: fileURL)
} catch {
    print(error)
}

Для чтения из списка:

do {
    let fileURL = ...
    let data = try Data(contentsOf: fileURL)
    let places = try PropertyListDecoder().decode([Place].self, from: data)
    print(places)
} catch {
    print(error)
}

Кстати, если вам нужен массив аннотаций для добавления на карту из этого массива places, вы можете:

let annotations = places.map { place -> MKPointAnnotation in
    let annotation = MKPointAnnotation()
    annotation.title = place.name
    annotation.coordinate = CLLocationCoordinate2D(latitude: place.latitude, longitude: place.longitude)
    return annotation
}
0 голосов
/ 08 июля 2019

Рассмотрим что-то более гибкое в форме структуры, соответствующей 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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...