Search code examples
swiftfirebaseuiviewcontrollermkmapviewmkannotationview

Pass text from MKMarkerAnnotation to different view controller


I am trying to pass text from my markers on MKMapView to a different view controller when the markers are tapped. I tried using one method after reading online but since the view controller I'm passing the text to doesn't have a navigation controller, I don't think it will work. Note that I am also using Firebase to retrieve data that will be displayed on markers and the reason the view controller looks odd is becuase I am using ISHPullUp

Visual Representation: https://i.sstatic.net/uv4qp.jpg

Code from TopViewController (MKMapView and MKMarker data)

var mainTitle = ""

.

Database.database().reference().child("posts").observeSingleEvent(of: .value, with: { (snapshot) in
        for snap in snapshot.children {
            let postSnap = snap as! DataSnapshot
            if let dict = postSnap.value as? [String:AnyObject] {
                let title = dict["title"] as! String
                let locationName = dict["location"] as! String
                let discipline = dict["category"] as! String
                let coordinate = CLLocationCoordinate2D(latitude: dict["lat"] as! Double, longitude: dict["long"] as! Double)
                let artwork = Artwork(title: title, locationName: locationName, discipline: discipline, coordinate: coordinate)
                self.mapView.addAnnotation(artwork)
            }
        }
    })

.

extension TopViewController: MKMapViewDelegate {
    func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
        guard let annotation = annotation as? Artwork else { return nil }
        let identifier = "marker"
        var view: MKMarkerAnnotationView
        if let dequeuedView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier)
            as? MKMarkerAnnotationView {
            dequeuedView.annotation = annotation
            view = dequeuedView
        } else {
            view = MKMarkerAnnotationView(annotation: annotation, reuseIdentifier: identifier)
            mainTitle = annotation.title!
        }
        return view
    }

    func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
        let myVC = storyboard?.instantiateViewController(withIdentifier: "bottom") as! BottomViewController // Didn't work
        myVC.stringPassed = mainTitle
        navigationController?.pushViewController(myVC, animated: true)
        print(mainTitle)
    }
}

Code from BottomViewController (View Controller I'm trying to send the text to)

var stringPassed = ""

override func viewDidLoad() {
    super.viewDidLoad()

    toplabel.text = stringPassed
}

Code from ViewController

class ViewController: ISHPullUpViewController {
    private func commonInit() {
        let storyBoard = UIStoryboard(name: "Main", bundle: nil)
        let contentVC = storyBoard.instantiateViewController(withIdentifier: "content") as! TopViewController
        let bottomVC = storyBoard.instantiateViewController(withIdentifier: "bottom") as! BottomViewController
        contentViewController = contentVC
        bottomViewController = bottomVC
        bottomVC.pullUpController = self
        contentDelegate = contentVC
        sizingDelegate = bottomVC
        stateDelegate = bottomVC
    }
}

Solution

  • You need to implement didSelect delegate method of MKMapViewDelegate

    func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
            if view.annotation is MKUserLocation {
                return
            }
            let ann = view.annotation as! Artwork
            let storyBoard = UIStoryboard(name: "Main", bundle: nil)
            let bottomVC = storyBoard.instantiateViewController(withIdentifier: "bottom") as! BottomViewController
            bottomViewController = bottomVC
            bottomVC.pullUpController = self
            sizingDelegate = bottomVC
            vc.stringPassed = ann.title
    }
    

    //

    override func prepare(for segue: UIStoryboardSegue, sender: Any?){
        if segue.identifier == "bottom" {
          let nextScene =  segue.destination  as! BottomViewController 
          nextScene.stringPassed = sender as! String
        }
    }
    

    //

    Also to be able to use push instead of segue embed TopViewController inside a UINavigationController