Passing Data over Segue From a mapView MKAnnotiation that has been tapped - swift

I am trying to pass data over a segue created by tapping an MkAnnotation callout using the calloutAccessoryControlTapped control. I want to go to the EventViewController and make a screen with more information about the MkAnnotation that was selected.
I've tried a number of difference methods including creating a custom class and trying to send that. The segue happens correctly but no data is passed to my second UIViewController (eventViewController).
I assume I am doing the wrong thing every time, but am finding it hard to debug the code due to the point at which I am assigning the data to the variable is also the trigger for the segue.
i.e. I am assuming the data isn't getting assigned at all, but the "selectedAnnotation" variable is getting passed across correctly but obviously its hard to tell.
override func prepare(for segue: UIStoryboardSegue, sender: (Any)?) {
if segue.identifier == "goToEventScreen" {
selectedAnnotation = mapView.selectedAnnotations.lastObject as? MKAnnotation
let destinationVC = segue.destination as! EventViewController
destinationVC.points = selectedAnnotation
}
}
}
'''
extension ViewController: MKMapViewDelegate {
func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView,
calloutAccessoryControlTapped control: UIControl){
performSegue(withIdentifier: "goToEventScreen", sender: self)
}
}
Thanks in advance.

You need to set your annotationView in the delegate method as the sender of performSegue method.
extension ViewController: MKMapViewDelegate {
func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
performSegue(withIdentifier: "goToEventScreen", sender: view)
}
}
Then in prepare for segue method:
override func prepare(for segue: UIStoryboardSegue, sender: (Any)?) {
if segue.identifier == "goToEventScreen" {
if let annotationView = sender as? MKAnnotationView {
selectedAnnotation = annotationView.annotation
let destinationVC = segue.destination as! EventViewController
destinationVC.points = selectedAnnotation
}
}
}
What you do is getting the annotation from the selected annotationView and assigning it to the destinationVC's points.

Related

Value not passing between viewControllers

Struggling to get my viewControllers to send value from the main viewController to a second. I want it to happen on a button click, I'm going to get the value from the button and pass it to the new form. But it just isn't working.
Code for main ViewController
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func butClick(_ sender: UIButton) {
NSLog("Button Pressed : %#",[sender .currentTitle])
//var tt = [sender .currentTitle]
// Create the view controller
let vc = TimesTablesViewController(nibName: "TimesTablesViewController", bundle: nil)
vc.passedValue = "xx"
self.performSegue(withIdentifier: "pushSegue", sender: nil)
}
}
Code for second viewController called TimesTablesViewController:
class TimesTablesViewController: UIViewController {
#IBOutlet weak var titleLabel: UILabel!
var passedValue:String = ""
override func viewDidLoad() {
super.viewDidLoad()
titleLabel?.text = "\(passedValue) Times Table"
}
}
I've followed tutorials but can't seem to solve the problem! Thanks for any help!
Replace
self.performSegue(withIdentifier: "pushSegue", sender: nil)
with
self.present(vc,animated:true,completion:nil)
or ( if the current vc is inside a naigation )
self.navigationController?.pushViewController(vc,animated:true)
Using
self.performSegue(withIdentifier: "pushSegue", sender: nil)
is fit with storyboards not xibs and if this your case then you need to use the above line only inside the button action with implementing this method inside the source vc
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "pushSegue" {
if let nextViewController = segue.destination as? TimesTablesViewController{
nextViewController.passedValue = "xx"
}
}
}
I’m assuming that the new view controller is appearing, but you’re simply not seeing the data. If so, you’re evidently using storyboards. The TimesTablesViewController(nibName:bundle:) only works if you’re using XIB/NIBs and manually presenting new view controller.
If you’re really using storyboards, simplify your butClick method:
#IBAction func butClick(_ sender: UIButton) {
NSLog("Button Pressed")
performSegue(withIdentifier: "pushSegue", sender: self)
}
But implement prepare(for:sender:):
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let destination = segue.destination as? TimesTablesViewController {
destination.passedValue = "xx"
}
}
Assuming the above fixes your problem, I might suggest a further simplification. Notably, if your butClick(_:) method is really only calling performSegue, you can segue to this next scene without any #IBAction method at all:
remove butClick(_:) entirely;
remove the connection between the button and the butClick method in IB, on the “Connections Inspector” tab in the right panel; and
control-drag from the button previously hooked up to butClick(_:) to the scene for TimesTablesViewController.
That will simplify your code further.

MKPointAnnotation go to another view

I would like to know how can I go to another view when I tap title on
MKPointAnnotation
func addPin(lat:Double, lng:Double) {
let testPin = CLLocationCoordinate2D(latitude: lat, longitude: lng)
let dropPin = MKPointAnnotation()
dropPin.coordinate = testPin
dropPin.title = "123456"
mapView.addAnnotation(dropPin)
}
I need to segue with identifier "More"
Please add this delegate method in your code and check it
func mapView(mapView: MKMapView, didSelectAnnotationView view: MKAnnotationView){
performSegue(withIdentifier: "PlaceDetail", sender: nil)
}
You need to override this method from MKMapViewDelegate:
func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
performSegue(withIdentifier: "PlaceDetail", sender: nil)
}

Add button to MKPointAnnotation

Having a problem when i try to add a button in a annotation.
Before i've asked this question i've searched for answers on the following pages:
How to add a button to the MKPointAnnotation?
, Adding a button to MKPointAnnotation?
etc.
But all couldn't help me.
This what is tried to do:
var annotation1 = MKPointAnnotation()
annotation1.setCoordinate(locationKamer1)
annotation1.title = "Title1"
annotation1.subtitle = "Subtitle1"
// here i want to add a button which has a segue to another page.
mapView.addAnnotation(annotation1)
Don't know if what i try to do isn't working.
I'm experimenting with swift for the first time.
Hope someone can help me :)
Thanks in advance!
That answer in your first link is basically right, though it needs to be updated for Swift 2.
Bottom line, in answer to your question, you don't add the button when you create the annotation. You create the button when you create its annotation view in viewForAnnotation.
So, you should:
Set the view controller to be the delegate of the map view.
Make the view controller conform to the map view delegate protocol, e.g.:
class ViewController: UIViewController, MKMapViewDelegate { ... }
Add a segue from the view controller (not the button) to the next scene by control dragging from the view controller icon above the scene with the map view to the next scene:
Then select that segue and then give it a storyboard identifier ("NextScene" in my example, though you should use a more descriptive name):
Implement viewForAnnotation to add button as right accessory.
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
var view = mapView.dequeueReusableAnnotationViewWithIdentifier(annotationIdentifier)
if view == nil {
view = MKPinAnnotationView(annotation: annotation, reuseIdentifier: annotationIdentifier)
view?.canShowCallout = true
view?.rightCalloutAccessoryView = UIButton(type: .DetailDisclosure)
} else {
view?.annotation = annotation
}
return view
}
Implement calloutAccessoryControlTapped which (a) captures which annotation was tapped; and (b) initiates the segue:
var selectedAnnotation: MKPointAnnotation!
func mapView(mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
if control == view.rightCalloutAccessoryView {
selectedAnnotation = view.annotation as? MKPointAnnotation
performSegueWithIdentifier("NextScene", sender: self)
}
}
Implement a prepareForSegue that will pass the necessary information (presumably you want to pass the annotation and therefore have a annotation property in that second view controller).
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if let destination = segue.destinationViewController as? SecondViewController {
destination.annotation = selectedAnnotation
}
}
Now you can create your annotation like you were before:
let annotation = MKPointAnnotation()
annotation.coordinate = coordinate
annotation.title = "Title1"
annotation.subtitle = "Subtitle1"
mapView.addAnnotation(annotation)

Passing data with prepareForSegue doesn't work

I am using the MapKit and when you click on an annotation balloon you get directed to another view. The function I am using for this is:
func mapView(mapView: MKMapView!, annotationView: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
//get tag here
if(annotationView.tag == 0){
//Do for 0 pin
}
if control == annotationView.rightCalloutAccessoryView {
performSegueWithIdentifier("mapToCity", sender: self)
}
}
But the problem is that I can't pass the marker data to the next view. I tried using this function in the first view but I don't exactly know how to retrieve the data in the next view or if it is even saved in "CityDetails":
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if(segue.identifier == "mapToCity") {
var yourNextViewController = (segue.destinationViewController as! CityDetails)
}
}
In the second viewcontroller this:
println(CityDetails);
Only returns the location of CityDetails which is in my case Ontdek_Polen.CityDetails
If you want to use segue to pass data from one view to another view then use this code:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if(segue.identifier == "mapToCity") {
var yourNextViewController = segue.destinationViewController as! CityDetails
yourNextViewController.foo = "This is passed"
}
}
In your destination view don't forget to create an instance which will hold this value like this:
import UIKit
class CityDetails: UIViewController {
var foo = "" //this will hold your value
override func viewDidLoad() {
super.viewDidLoad()
println(foo) //This is passed
}
}
Don't forget to set the type of your instance in next view same as you want to pass from previous view.
And one more way to pass data from one view to another view is you can use NSUserDefaults as shown in below example:
func mapView(mapView: MKMapView!, annotationView: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
//get tag here
if(annotationView.tag == 0){
//Do for 0 pin
}
if control == annotationView.rightCalloutAccessoryView {
//set your object here
NSUserDefaults.standardUserDefaults().setObject("abcd", forKey: "yourKey")
performSegueWithIdentifier("mapToCity", sender: self)
}
}
This will store this value into disk so you can read this value anywhere into your project with yourKey.
This way you can read value from NSUserDefault:
import UIKit
class CityDetails: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let foo1 = NSUserDefaults.standardUserDefaults().objectForKey("yourKey") as! String
println(foo1) //abcd
}
}
And for more Info check THIS sample project where I am passing value with segue.
Hope this will help.
There is no reason to use the code (segue.destinationViewController as! CityDetails).
What I would recommend doing is instead of using the last bit of code to access the destination view controllers items just create an instance of the class and access its variables and data through dot notation.
ex. (in this example I am saying that the name of the destination vc is CityDetails)
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if(segue.identifier == "mapToCity") {
var yourNextViewController: CityDetails = CityDetails()
yourNextViewController.variable = 0 //example
}
}

How pass data from Mapkit to viewcontroller

I want to pass the data (quelmonument) from a pinpoint on a Mapkit to another viewcontroller. With this code just below, i could get the good value but i don't know i could do to pass the data.
func mapView(mapView: MKMapView!, annotationView: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
if control == annotationView.rightCalloutAccessoryView {
if let pinannotation = annotationView.annotation as? Artwork{
println("status was = \(pinannotation.quelmonument)")
var indexmonument = pinannotation.quelmonument
performSegueWithIdentifier("hugo", sender: self)
}
}
}
I have tried to send the value 2, and it's working, but instead of 2 i would like send "quelmonument" variable. Could you give me pls an hint ?
func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "hugo"
{
if let destinationVC = segue.destinationViewController as? MonumentViewController{
destinationVC.numberToDisplay = 2
}
}
}