I have a few moving parts in this one that I can't seem to stitch together, hopefully it is pretty straightforward.
Previous questions don't use a subclass and in this example there could be dozens of custom pins on the map and each pin passes specific variables to a new ViewController
Three Goals:
Capital
, I would like to add the image in #1 and then create additional variables to hold values that will be passed to a new SecondViewController
that includes (2) labels and a Picker View: for example label1 = "text1", label2 = "text2", and then grab a string from an array that contains multiple objects (i.e. the title for each row of the Picker)ViewController
to a new view controller named SecondViewController
and assign the values of subclass Capital
that are attached to the custom pin that was tapped to the new labels and picker view in the SecondViewController
Here is my code thus far:
Subclass named Capital.swift
import MapKit
import UIKit
class Capital: NSObject, MKAnnotation {
var title: String?
var coordinate: CLLocationCoordinate2D
var info: String
// here we would add the custom image in Goal #1
// here we would add the (2) values for label1 and label2 in Goal #2
// here we would add the array that contains multiple object in Goal #2
init(title: String, coordinate: CLLocationCoordinate2D, info: String) {
self.title = title
self.coordinate = coordinate
self.info = info
// add additional lines as needed
}
}
Here is my code for the ViewController.swift
import MapKit
import UIKit
class ViewController: UIViewController, MKMapViewDelegate {
@IBOutlet var mapView: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
let london = Capital(title: "London", coordinate: CLLocationCoordinate2D(latitude: 51.507222, longitude: -0.1275), info: "Home to the 2012 Summer Olympics.")
let oslo = Capital(title: "Oslo", coordinate: CLLocationCoordinate2D(latitude: 59.95, longitude: 10.75), info: "Founded over a thousand years ago.")
let paris = Capital(title: "Paris", coordinate: CLLocationCoordinate2D(latitude: 48.8567, longitude: 2.3508), info: "Often called the City of Light.")
let rome = Capital(title: "Rome", coordinate: CLLocationCoordinate2D(latitude: 41.9, longitude: 12.5), info: "Has a whole country inside it.")
let washington = Capital(title: "Washington DC", coordinate: CLLocationCoordinate2D(latitude: 38.895111, longitude: -77.036667), info: "Named after George himself.")
mapView.addAnnotations([london, oslo, paris, rome, washington])
}
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
let identifier = "Capital"
if annotation is Capital {
if let annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier) {
annotationView.annotation = annotation
return annotationView
} else {
let annotationView = MKPinAnnotationView(annotation:annotation, reuseIdentifier:identifier)
annotationView.isEnabled = true
annotationView.canShowCallout = true
let btn = UIButton(type: .detailDisclosure)
annotationView.rightCalloutAccessoryView = btn
//annotationView.image = UIImage(named: "#imageLiteral(resourceName: ",pin,")")
return annotationView
}
}
return nil
}
Here we add the custom callout variables that are specific to the city that was pressed and push these to the SecondViewController
func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
let capital = view.annotation as! Capital
let placeName = capital.title
let placeInfo = capital.info
//Add custom image + (2) labels + and the array that contains multiple objects to be passed to the Picker 'view in the SecondViewController
// Upon the User tapping the above button we push all the variables stored in Capital attached to the current city pin that was pressed to the new SecondViewController
// Send the View Controller to the SecondViewController programically
let SecondViewController = self.storyboard?.instantiateViewController(withIdentifier: "SecondViewController")
self.show(SecondViewController!, sender: nil)
}
Here is my code for the SecondViewController
import UIKit
class SecondViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource {
@IBOutlet weak var pickerView: UIPickerView!
var cityName = 0
//the values here are pulled from the custom pin that was pressed in the previous ViewController
var Array = ["object1 from custom pin","object2 from custom pin,","object3 from custom pin"]
@IBOutlet weak var label1: UILabel!
@IBOutlet weak var label2: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
pickerView.delegate = self
pickerView.dataSource = self
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
return Array[row]
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
return Array.count
}
func numberOfComponents(in pickerView: UIPickerView) -> Int {
return 1
}
@IBAction func submit(_ sender: Any) {
if (cityName == 0){
label1.text = "object1 from custom pin"
}
else if(cityName == 1){
label1.text = "object2 from custom pin"
}
else{
label1.text = "object3 from custom pin"
// continued...
}
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
cityName = row
}
}
Appreciate any help
It seems that you're very close. In calloutAccessoryControlTapped
, you're get getting the place name and info. I'm assuming that's what you want to pass to the second view controller, so go ahead and do so before you show
it:
func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
let capital = view.annotation as! Capital
let placeName = capital.title
let placeInfo = capital.info
let secondViewController = sUIKeyInputUpArrowtoryboard!.instantiateViewController(withIdentifier: "SecondViewController") // I'm not sure why you're not just doing `storyboard.instantiateViewController(...); do you really have multiple storyboards floating around?
secondViewController.placeName = placeName
secondViewController.placeInfo = placeInfo
show(secondViewController, sender: self)
}
That presumes, of course, that your second view controller is has those placeName
and placeInfo
properties, e.g.
class SecondViewController {
var placeName: String!
var placeInfo: String!
override func viewDidLoad() {
// use placeName and placeInfo to populate UI controls as necessary
}
}
I confess, though, that your question has a ton of unrelated code that's hard to make sense of, so it's not clear precisely what you need to do. But the idea is clear, that calloutAccessoryControlTapped
should
show
it; and Note, calloutAccessoryControlTapped
in the first view controller cannot update the UI controls in the second view controller directly (since the controls for that view controller have not yet been hooked up to the outlets in the storyboard), but rather just passes whatever data that second view controller needs. Then that second view controller will configure its controls in its viewDidLoad
.