iosarraysswiftdictionarypins

Resetting saved map pins, iOS Swift


I am working on a small map application, so far I have the code to drop map pins and save them so they remain once the app is reopened, this class is for the main view controller:

import UIKit
import MapKit
import CoreLocation

class ViewController: UIViewController, MKMapViewDelegate, CLLocationManagerDelegate, UISearchBarDelegate, UIPopoverPresentationControllerDelegate {

    var location: CLLocation!
    let locationManager = CLLocationManager()

    @IBOutlet weak var placesMap: MKMapView!
    @IBOutlet weak var addButton: UIBarButtonItem!
    @IBOutlet weak var moreStuff: UIButton!

    // Popover button action
    @IBAction func moreStuff(sender: AnyObject) {
        self.performSegueWithIdentifier("showMoreStuff", sender:self)
        moreStuff.adjustsImageWhenHighlighted = false
    }

    @IBAction func addButton(sender: AnyObject) {
        let annotation = MKPointAnnotation()
        annotation.coordinate = CLLocationCoordinate2D(latitude: self.placesMap.userLocation.coordinate.latitude, longitude: self.placesMap.userLocation.coordinate.longitude)
        self.placesMap.addAnnotation(annotation)
        self.locationManager.startUpdatingLocation()
    }

    // Location function
    func locationManager(manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        let location = locations.last
        let center = CLLocationCoordinate2D(latitude: location!.coordinate.latitude, longitude: location!.coordinate.longitude)
        let region = MKCoordinateRegion(center: center, span: MKCoordinateSpan(latitudeDelta: 0.004, longitudeDelta: 0.004))
        self.placesMap?.setRegion(region, animated: true)
        self.locationManager.stopUpdatingLocation()
        let locationDictionary:[String:Double] = ["latitude":center.latitude,"longitude":center.longitude]
        var locationArray = [[String:Double]]()
        if NSUserDefaults.standardUserDefaults().objectForKey("locationArray") != nil {
             locationArray = NSUserDefaults.standardUserDefaults().objectForKey("locationArray") as! [[String:Double]]
    }
        locationArray.append(locationDictionary)
        NSUserDefaults.standardUserDefaults().setObject(locationArray, forKey: "locationArray")
        NSUserDefaults.standardUserDefaults().synchronize()
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        self.locationManager.delegate = self
        self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
        self.locationManager.requestWhenInUseAuthorization()
        self.locationManager.startUpdatingLocation()
        self.placesMap?.showsUserLocation = true
        if NSUserDefaults.standardUserDefaults().objectForKey("locationArray") != nil {
            for dictionary in NSUserDefaults.standardUserDefaults().objectForKey("locationArray") as! [[String:Double]]{
                let center = CLLocationCoordinate2D(latitude: dictionary["latitude"]!, longitude: dictionary["longitude"]!)
                let annotation = MKPointAnnotation()
                annotation.coordinate = center
                self.placesMap?.addAnnotation(annotation)
            }
        }
    }

I want to add a button which allows all pins (memories) to be reset at once. This button is located on a new scene and class, called "PopoverOptions". I have the following code from the class which should do this, but it does not seem to be functioning as no pins disappear from the map once it is pressed by the user!

@IBOutlet weak var resetMemories: UIButton!

@IBAction func resetMemories(sender: AnyObject) {
    func removeStoredLocations(){
        NSUserDefaults.standardUserDefaults().removeObjectForKey("locationArray")
        NSUserDefaults.standardUserDefaults().synchronize()
    }
}

Any idea why the pins aren't being removed? I have ensured that the class is linked correctly as well as the buttons outlet / action.


Solution

  • You clear out your user defaults key, but don't change the map view on the view controller that shows those pins. You need to call removeAnnotations to remove the annotations from the map.

    You could add a viewWillAppear method that detects that your annotations have been deleted and remove them. Something like this:

    func viewWillAppear(_ animated: Bool)
    {
      if NSUserDefaults.standardUserDefaults().objectForKey("locationArray") == nil 
      {
        if let annotations = self.placesMap.annotations
          self.placesMap?.removeAnnotations(annotations)
      }
    }
    

    The code above is written to only remove the annotations from the map if the entire annotations dictionary was deleted from userDefaults. That way you avoid reloading the annotations every time the view controller regains focus.

    BTW, you said your new scene is called "PopoverOptions." If the scene is presented in a popover then the above might not work. (I don't think viewWillAppear gets called on a view controller when a popover is dismissed, but I don't remember for sure.)