1

I am making a small map application. I want to be able to reset the pins (memories), the user has dropped. I want this to be done through a "Reset memories" button, displayed via Popover:

enter image description here

I have this code for my main view controller class which handles the map etc:

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

Here is the outlet and action for the Reset memories button, this code is stored in a new class for the popover named "PopoverOptions". Currently when the button is pressed, no pins are removed from the map:

@IBOutlet weak var resetMemories: UIButton!

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

Any help to get this working is appreciated, I am new to Swift

Oscar
  • 511
  • 2
  • 10
  • 25

1 Answers1

0

You are updating the backing array but not the map view itself. Add placesMap.removeAnnotations(placesMap.annotations) to resetMemories().


Updated: since the action is in another file, fire a notification from resetMemories():

NSNotificationCenter.defaultCenter().postNotificationName("memoriesUpdated", object: nil)

Then in your view controller listen for the notification and update the pins:

NSNotificationCenter.defaultCenter().addObserverForName("memoriesUpdated", object: nil, queue: nil) { [weak self] (n) -> Void in
    // remove existing annotations
    if let annotations = self?.placesMap.annotations {
         self?.placesMap.removeAnnotations(annotations)
    }

    // add new annotations (if any)
    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)
        }
    }
}
jszumski
  • 7,430
  • 11
  • 40
  • 53
  • Thanks for your reply :) I tried your suggestion but as the resetMemories() function is in a new class, it cannot see placesMap! Do you have any further suggestion? – Oscar Mar 28 '16 at 15:01
  • You could fire a notification from `resetMemories()` and then update the annotations when receiving that notification. I'll edit my answer. – jszumski Mar 28 '16 at 15:04
  • Thanks again, I will try this now. The view controller code should be inserted into viewDidLoad function correct? – Oscar Mar 28 '16 at 15:12
  • Yes, you'll also want to stop observing the notification when appropriate (probably in `dealloc`). – jszumski Mar 28 '16 at 15:13
  • Okay thanks :) I inserted the code and now I get an error on the third line stating "Value of optional type '[MKAnnotation]?' not unwrapped, did you mean to use ! or ?" When I apply the suggested fix it runs without error but still no change to the pins on the map when the button is pressed :( – Oscar Mar 28 '16 at 15:17