如何将plist用作快速存储?

时间:2019-07-08 14:21:35

标签: swift xcode plist

我用MapKit View编写了一个应用程序,并且在地图上显示了多个注释。我使用数组表示地点的经度,纬度和名称,并且效果很好。但是,随着添加的地点越来越多,很难找到特定地点的数据。我想使用plist将每个位置的数据存储在自己的数组中,但是我无法找到如何访问plist和所需的特定数据。

我只尝试创建一个plist,并在创建的Root Dictionary中创建了一个数组,每个数组都包含Item 0作为字符串“ Place Name”,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

    }

}

我想从plist中数组的第0项(位置的名称)中获取该值到place.subtitle中。

2 个答案:

答案 0 :(得分:1)

您可以使用enter image description herePropertyListEncoder

为此,您可以创建一个符合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)
]

要将其保存到plist中:

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)
}

要从plist中读取内容:

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
}

答案 1 :(得分:0)

以符合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 or for x in ymap,特别是如果该值仅 用作索引。如果值本身很重要(例如title = "This is section \(idx)"),那么.enumerated是您的朋友。

提示::如果您希望保存的数据更易于阅读/编辑,或者由Web服务提供,请考虑使用JSONEncoder / JSONDecoder。