daanyyaal
daanyyaal

Reputation: 301

Swift: Data is not being stored in variable when passing through VC

I'm trying to store the name of a map pin in a variable, then display it on a label on my second VC.

Currently, this is what I've got.

FirstVC.swift

//Perform segue when callout has been tapped
func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {

     self.performSegue(withIdentifier: "showAnnotationInfo", sender:view)

        }


func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {

    print("Annotation selected")

    if let annotation = view.annotation as? POIAnnotations {
        print("Your annotation title is: \(annotation.title!)")

        // Instantiate ShopDetailViewController
        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        let destVC = storyboard.instantiateViewController(withIdentifier: "shopDetailVC") as! ShopDetailViewController

        destVC.shopNameData = annotation.title!
        print("Shop name data has the value: \(destVC.shopNameData)")

    }
}

ShopDetailViewController.swift

class ShopDetailViewController: UIViewController {

@IBOutlet weak var shopName: UILabel!

var shopNameData = "data"

override func viewDidLoad() {
    super.viewDidLoad()

    self.shopName.text = self.shopNameData
    print(shopNameData)

  }

}

What is happening is, when I attempt to store annotation.title in shopNameData, there is no problem.

However, when I click on the annotation, the data from annotation.title is no longer stored in shopNameData and simply displays the default data.

enter image description here

I'm not sure where I've gone wrong here.

EDIT

I've included where I present ShopDetailViewController.

Upvotes: 5

Views: 159

Answers (2)

dlbuckley
dlbuckley

Reputation: 685

You are simply creating an instance of the ShopDetailViewController, setting the value and then doing nothing with it. The instance of ShopDetailViewController that you created goes out of scope and gets deallocated.

How are you presenting the ShopDetailViewController? Are you using a segue? If you are then you should override the prepareForSegue() method where you will get an instantiated version of the ShopDetailViewController which will be presented and not go out of scope and then simply set the shopNameData property in there.

EDIT:

Thanks for clarifying the way you are presenting the view controller. So to answer you comment:

You need to go to FirstVC and add something like the following code:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

    if let viewController = segue.destination as? ShopDetailViewController,
        let annotationView = sender as? MKAnnotationView,
        let annotation = annotationView.annotation as? POIAnnotations {

        viewController.shopNameData = annotation.title
    }
}

Then after that you can just remove the code in your func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) method and keep the code in your func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) method.

This way you are simply calling present and passing the MKAnnotationView through as the sender, then pulling out the relevant information when the segue is preparing to present your view controller. I hope that makes sense.

Upvotes: 2

Sasha Kozachuk
Sasha Kozachuk

Reputation: 1303

Override prepare for segue method like so:

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if (let view = sender as! MKAnnotationView) && (segue.identifier == "showAnnotationInfo") {
           if annotation = view.annotation as? POIAnnotation {
              let destVC = segue.destination as! ShopDetailViewController
              destVC.shopNameData = annotation.title!
           }
        }
    }

Upvotes: 0

Related Questions