How pass data from Mapkit to viewcontroller - swift

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

Related

Set condition on a segue function swift

In a single button, i put both alart system and a pop up view. If the text fields are blank then it will send an alart. If everything is okay then it will show popup view. Alart system and pop up is conflicting. How do I set conditon to segue function when to perform or not?
The function is not written proper. I can understand. But I am confused writing it. How do i call the overrride func?
func stateCondition(state: Bool) {
if state {
print("Entered into the state") //entering into the func
func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "info"{
_ = segue.destination as! InfoViewController
}
if segue.identifier == "popUp" {
let vc = segue.destination as! PopUpViewController
vc.age = Double(ageTextField.text!)!
vc.gender = genderTextField.text!
vc.bmi = Double(bmiLabel.text!)!
print("Entered into the segue") //is not entering into this func
}
}
}
}
Try to read the code and comments.
First of all, the method func prepare(for segue: UIStoryboardSegue, sender: Any?) must not be in another method. Somehow you managed to squeeze it in func stateCondition(state: Bool) . Second you are not calling performSegue(withIdentifier: identifier, sender: self) anywhere. You probably should :) Check out the code, hope it helps. I remember my first segue, it took me some time to understand what is going on.
class ViewController: UIViewController {
#IBOutlet private var ageTextField: UITextField!
#IBOutlet private var genderTextField: UITextField!
#IBOutlet private var bmiLabel: UILabel!
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// 3
// This method gets called and there you do your stuff with respective VCs
if segue.identifier == "info", let infoViewController = segue.destination as? InfoViewController {
// 3.1
// If the identifer is set to INFO then you go to the InfoViewController and assigne message
infoViewController.message = "Some fields are empty"
} else if segue.identifier == "popUp", let popUpViewController = segue.destination as? PopUpViewController {
// 3.2
// If the identifer is set to POPUP then you go to PopUpViewController and assign age, gender and bmi
popUpViewController.age = "33"
popUpViewController.gender = "male"
popUpViewController.bmi = "20"
} else {
print("Identifer is none of the above")
}
}
#IBAction private func buttonTapped(_ sender: Any) {
// 1.
// First you need to figure out where you want to take the user
// You do that in the method getSegueIdentifier() where you get the identifier
let identifier = getSegueIdentifier()
// 2.
// Then you performSegue with that identifer
performSegue(withIdentifier: identifier, sender: self)
}
private func getSegueIdentifier() -> String {
if ageTextField.text?.isEmpty == true && genderTextField.text?.isEmpty == true && bmiLabel.text?.isEmpty == true {
return "info"
} else {
return "popUp"
}
}
}
class InfoViewController: UIViewController {
var message = ""
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
showAlert()
}
func showAlert() {
// show alert with message
print(message)
}
}
class PopUpViewController: UIViewController {
var age = ""
var gender = ""
var bmi = ""
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
showPopUp()
}
func showPopUp() {
// show popUp with age gender and bmi
print(age, gender, bmi)
}
}
There is general misunderstanding: You must not call prepare(for segue – besides the syntax is wrong anyway – the function is called by the framework just before the segue is performed.
You probably mean something like
func stateCondition(state: Bool) {
if state {
print("Entered into the state") //entering into the func
performSegue(withIdentifier: "info", sender: nil)
} else {
performSegue(withIdentifier: "popUp", sender: nil)
}
}
func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "popUp" {
let vc = segue.destination as! PopUpViewController
vc.age = Double(ageTextField.text!)!
vc.gender = genderTextField.text!
vc.bmi = Double(bmiLabel.text!)!
print("Entered into the segue") //is not entering into this func
}
}

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

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.

Add Id for each annotation in MapKit

I need to add an Id for each annotation in map to open new view controller by clicking on info button in annotation , my problem is in prepare and perform segue, I created it, but I don't know how to pass the id to the segue.
I created sub class for annotation to store the ID that comes from JSON
Thats parts of my code :
Getting all data from JSON :
for location in self.locations {
let annotation:MyAnnotation = MyAnnotation()
annotation.title = location["truck_name"] as? String
annotation.customTruckId = location["truck_id"] as? String
annotation.coordinate = CLLocationCoordinate2D(latitude: (location["coor_x"] as! NSString).doubleValue, longitude: (location["coor_y"] as! NSString).doubleValue)
self.AllMapView.addAnnotation(annotation)
}
Sub class I created:
class MyAnnotation : MKPointAnnotation {
var customTruckId : String?
}
Problem is here in segue :
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if (segue.identifier == "ShowTruckFromMap") {
let des_VC = segue.destination as! TruckDetailsVC
des_VC.truck_id = "How to get Id here !"
}
}
func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
if control == view.rightCalloutAccessoryView {
performSegue(withIdentifier: "ShowTruckFromMap", sender: self)
}
}
Thanks
You can show your UIViewController without using Segue.
You must at first put an identifier to your UIViewController in :
identity Inspector -> Identity -> storyboard ID = TruckDetailsVCIdentifier
func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
if control == view.rightCalloutAccessoryView {
let mainStoryboard:UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let desController = mainStoryboard.instantiateViewController(withIdentifier: "TruckDetailsVCIdentifier") as! TruckDetailsVC
let TruckAnnotation = view.annotation as? MyAnnotation
desController.truck_id = (TruckAnnotation?.customTruckId!)!
show(desController, sender: self)
}
}
I found Answer:
func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
if control == view.rightCalloutAccessoryView {
let mainStoryboard:UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let desController = mainStoryboard.instantiateViewController(withIdentifier: "TruckDetailsVC") as! TruckDetailsVC
let TruckAnnotation = view.annotation as? MyAnnotation
desController.truck_id = (TruckAnnotation?.customTruckId!)!
show(desController, sender: self)
}
}
Thanks for all

Swift: I need to get an index of one of UIVIew collections to know which is tapped

I need to get an index of one of UIView collections to know which is tapped then link to a corresponding array element in the next screen. Problem seems sender! that I have the error message:
Could not cast value of type 'UITapGestureRecognizer' (0x107dcdc20) to 'UIView' (0x107dc2578).
(I used UIView to create color tiles. Should I use label or buttons instead of UIView?)
import UIKit
class ColoringViewController: UIViewController {
var coloringItem: ColoringItem?
var colorListTileArray = [UIView]()
#IBOutlet var colorListTile: [UIView]! // UIView color tiles
override func viewDidLoad() {
super.viewDidLoad()
if coloringItem != nil {
for (var i = 0; i<colorListTile.count; i++) {
colorListTileArray += [colorListTile[i]]
}
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "showColoringDescriptionSegue" {
let tappedTile = sender!.self //<- doesn't work
//let tappedTile = sender!.view as! UIView <- doesn't work either :(
let colorIndex = colorListTileArray.indexOf(tappedTile as! UIView)
print(colorIndex)
}
}
#IBAction func showColoringDescription(sender: AnyObject) {
performSegueWithIdentifier("showColoringDescriptionSegue", sender: sender)
}
}
You are close. The sender to showColoringDescription is the UITapGestureRecognizer. Change the signature to take one of those. Then pass sender.view to performSegueWithIdentifier.
In prepareForSegue, cast sender to UIView and use that for the lookup in the colorListTileArray:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "showColoringDescriptionSegue" {
let tappedTile = sender as! UIView
let colorIndex = colorListTileArray.indexOf(tappedTile)
print(colorIndex)
}
}
#IBAction func showColoringDescription(sender: UITapGestureRecognizer) {
performSegueWithIdentifier("showColoringDescriptionSegue", sender: sender.view)
}
Since you're using a UITapGestureRecognizer to initiate the segue, the recognizer will be the sender in prepareForSegue You can get the associated view using the view property:
if let recognizer = sender as UITapGestureRecognizer {
let view = recognizer.view
...
}

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