当我离开应用程序时,如何保存我的 MapView 注释?

How can I get my MapView annotations to save when I leave the app?

func addPin(_ sender: UILongPressGestureRecognizer) {

    let location = sender.location(in: self.mapView)
    let locCoord = self.mapView.convert(location, toCoordinateFrom: self.mapView)

    let annotation = MKPointAnnotation()

    annotation.coordinate = locCoord
    annotation.title = titleTextField.text

    self.mapView.addAnnotation(annotation)

    print("This will become the annotation title: \(titleTextField.text).")
    print(annotation.coordinate.latitude, annotation.coordinate.longitude)

}

我是 swift 的新手,想知道如何在离开应用程序后保存我的注释。另外,如果用户没有拿起手指,我该如何阻止形成多个注释?

您可能需要做的是将 MKPointAnnotation 作为 Data 存储在 UserDefaults 中。为此,您将从所有 mapView 的注释创建一个字典数组:

func addPin(_ sender: UILongPressGestureRecognizer) {

    let location = sender.location(in: self.mapView)
    let locCoord = self.mapView.convert(location, toCoordinateFrom: self.mapView)

    let annotation = MKPointAnnotation()

    annotation.coordinate = locCoord
    annotation.title = titleTextField.text

    self.mapView.addAnnotation(annotation)

    //Create a dictionary from the annotation
    let newAnnotationDict = [
        "lat": locCoord.latitude
        "lng": locCoord.longitude
        "title": annotation.title
    ]

    //Pull the stored annotations data
    var annotationsArray: [[String:Any]]!
    var annotationsData = UserDefaults.standard.data(forKey: "StoredAnnotations")

    //If the data is nil, then set the new annotation as the only element in the array
    if annotationsData == nil {
        annotationsArray = [newAnnotationDict]
    } else {
        //If it isn't nil, then convert the data into an array of dicts
        do {
            //Convert this data into an array of dicts
            annotationsArray = try JSONSerialization.jsonObject(with: annotationsData, options: []) as! [[String:Any]]
            annotationsArray.append(newAnnotationDict)
        } catch {
            print(error.localizedDescription)
        }

    }

    do {

        //Use JSONSerialization to convert the annotationsArray into Data
        let jsonData = try JSONSerialization.data(withJSONObject: annotationsArray, options: .prettyPrinted)

        //Store this data in UserDefaults
        UserDefaults.standard.set(jsonData, forKey: "StoredAnnotations")
    } catch {
        print(error.localizedDescription)
    }

    print("This will become the annotation title: \(titleTextField.text).")
    print(annotation.coordinate.latitude, annotation.coordinate.longitude)

}

然后,当再次打开视图控制器时,您需要从 UserDefaults 中提取此 Data 并将其解析为 MKPointAnnotation 个对象的数组。

class MapViewController: UIViewController {

    //Whenever the view loads, check if there were any annotations stored last time
    override func viewDidLoad() {
        super.viewDidLoad()

        //Check if the data for "StoredAnnotations" exists
        if UserDefaults.standard.data(forKey: "StoredAnnotations") != nil {

            var storedAnnotationObjects = [MKPointAnnotation]()

            do {

                //Get the data from UserDefaults
                let storedAnnotationsData = UserDefaults.standard.data(forKey: "StoredAnnotations")!

                //Convert this data into an array of dictionaries
                let storedAnnotationsArray = try JSONSerialization.jsonObject(with: storedAnnotationsData, options: []) as! [[String:Any]]

                for dict in storedAnnotationsArray {
                    //Initialize a new annotation and set the annotation's properties
                    let newAnnotation = MKPointAnnotation()
                    newAnnotation.coordinate = CLLocationCoordinate2D(latitude: dict["lat"] as! CGFloat, longitude: dict["lng"] as! CGFloat)
                    newAnnotation.title = dict["title"] as! String
                    newAnnotationObjects.append(newAnnotation)
                }

                //Add the annotation to the mapView
                self.mapView.annotations = storedAnnotationObjects
            } catch {
                print(error.localizedDescription)
            }
        }
    }

    ...

}

如果注释被删除,您将需要类似地将存储的数据转换为字典数组并删除适当的对象并更新数据。

在 iOS 上有很多持久性策略,并且取决于许多因素,例如您将保存多少注释、数据的敏感程度等。

Apple 的持久性指南在这里:https://developer.apple.com/library/archive/referencelibrary/GettingStarted/DevelopiOSAppsSwift/PersistData.html

尽管我并不是真的建议这样做,但您也许可以自己序列化对象。相反,请考虑编写自己的符合 Codable 的注释类型,以使持久化更安全、更容易。本教程合理地涵盖了您的用例:

https://www.raywenderlich.com/5247-core-location-tutorial-for-ios-tracking-visited-locations#toc-anchor-022

令人恼火的是 CLLocationCoordinate2D 不是 Codable 本身,这就是为什么你必须跳过一些障碍。