I am struggling with my iOS code. The overall goal of the project is to show the pins on the map, I've tried multiple ways to make the pins appear on the map such as the below, I am not sure what I am doing wrong. The code runs fine, the pins are not appearing. I've made changes to my functions but seem to get the same error. Any insight on what I may be missing?
"import UIKit
import MapKit
class MapViewController: UIViewController, MKMapViewDelegate {
#IBOutlet weak var mapView: MKMapView!
#IBOutlet weak var activityIndicator: UIActivityIndicatorView!
#IBOutlet weak var logout: UIBarButtonItem!
#IBOutlet weak var refresh: UIBarButtonItem!
#IBOutlet weak var pinDrop: UIBarButtonItem!
var studentLocation = [StudentInformation]()
var annotations = [MKPointAnnotation]()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func viewDidAppear (_ animated: Bool) {
super.viewDidAppear(true)
getStudentPins()
}
#IBAction func refresh(_ sender: UIBarButtonItem) {
getStudentPins ()
}
#IBAction func logout(_ sender: UIBarButtonItem) {
self.activityIndicator.startAnimating()
UdacityClient.logout {
DispatchQueue.main.async {
self.dismiss(animated: true, completion: nil)
self.activityIndicator.stopAnimating()
}
}
}
#IBAction func addLocation(_ sender: Any) {
performSegue(withIdentifier: "addLocation", sender: nil)
}
func getStudentPins () {
self.activityIndicator.startAnimating()
UdacityClient.getStudentLocations() { locations, error in
self.mapView.removeAnnotations(self.annotations)
self.annotations.removeAll()
self.studentLocation = locations ?? []
for dictionary in locations ?? [] {
let latitude = CLLocationDegrees(dictionary.latitude ?? 0.0)
let longitude = CLLocationDegrees(dictionary.longitude ?? 0.0)
let coordinate = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
let firstName = dictionary.firstName
let lastName = dictionary.lastName
let mediaURL = dictionary.mediaURL
let annotation = MKPointAnnotation()
annotation.coordinate = coordinate
annotation.title = "\(firstName) \(lastName)"
annotation.subtitle = mediaURL
self.annotations.append(annotation)
}
DispatchQueue.main.async {
self.mapView.addAnnotations(self.annotations)
self.activityIndicator.stopAnimating()
}
}
}
private func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotation? {
let reuseId = "pin"
var pinView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseId) as? MKPinAnnotationView
if pinView == nil {
pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
pinView!.canShowCallout = true
pinView!.pinTintColor = .green
pinView!.rightCalloutAccessoryView = UIButton(type: .detailDisclosure)
}
else {
pinView!.annotation = annotation
}
return pinView?.annotation
}
func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
if control == view.rightCalloutAccessoryView {
if let toOpen = view.annotation?.subtitle {
openLink(toOpen ?? "")
}
}
}
}"
They're called annotations in the MapKit and you should instantiate them like so:
let annotation = MKPointAnnotation()
then in the viewDidLoad() method just set the coordinates and add them to the map like:
annotation.coordinate = CLLocationCoordinate2D(latitude: 11.12, longitude: 12.11)
mapView.addAnnotation(annotation)
The numbers are your coordinates. Try by adding sample coordinates on the map first and then add all coordinates which you are getting from the client.
you can also add more information using:
annotation.title = "Your text here"
//You can also add a subtitle that displays under the annotation such as
annotation.subtitle = "One day I'll go here..."
Related
So I have a MapView which adds a pin to the current user location. Also I have two textfields which displays the coordinates of the pin. I want to add two features:
When I drag and drop the pin, I want to update the coordinates inside the textfields.
When I edit the coordinates in the textfield, it should move the pin to the updated coorinates from the textfields.
Here my code where i handle everything for MapView. Im still pretty new to coding, so the code could be confusing, sorry for that.
class LocateVC: UIViewController, CLLocationManagerDelegate, MKMapViewDelegate {
#IBOutlet weak var mapView: MKMapView!
#IBOutlet weak var finishedLocateButton: UIButton!
#IBOutlet weak var relocateButton: UIButton!
var coordinates: [[Double]]!
var latTitleLabel:[String]!
var latValueLabel:[String]!
var lngTitleLabel:[String]!
var lngValueLabel: [String]!
var isEdited = false
var customCallout: UIView?
//Important to track location
let locationManager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
view.layer.backgroundColor = Colors.grey.cgColor
//button titles
relocateButton.isHidden = true
relocateButton.setTitle("Relocate", for: .normal)
finishedLocateButton.setTitle("Continue", for: .normal)
navigationItem.title = "Location"
// Ask for Authorisation from the User.
self.locationManager.requestAlwaysAuthorization()
self.locationManager.requestWhenInUseAuthorization()
locationManager.delegate = self
self.mapView.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyNearestTenMeters
if isEdited == false {
if CLLocationManager.locationServicesEnabled() {
addPin()
}
}
// Latitude,Longitude
coordinates = [
[ProductData.shared.latitude!, ProductData.shared.longitude!],
]
} //end of viewDidLoad
override func viewWillAppear(_ animated: Bool) {
super.dismiss(animated: animated)
}
public func removePin() {
}
func dropPinFor(placemark: MKPlacemark) {
for annotation in mapView.annotations {
if annotation.isKind(of: MKPointAnnotation.self) {
// mapView.removeAnnotation(annotation) // removing the pins from the map
}
}
let annotation = MKPointAnnotation()
annotation.coordinate = placemark.coordinate
mapView.addAnnotation(annotation)
}
//1
public func addPin() {
if isEdited == false {
ProductData.shared.latitude = locationManager.location?.coordinate.latitude
ProductData.shared.longitude = locationManager.location?.coordinate.longitude
}
self.mapView.delegate = self
// adds an annotation to coordinates from productData
let point = ProductAnnotation(coordinate: CLLocationCoordinate2D(latitude: ProductData.shared.latitude! , longitude: ProductData.shared.longitude!))
self.mapView.addAnnotation(point)
// 3
let region = MKCoordinateRegion(center: CLLocationCoordinate2D(latitude: ProductData.shared.latitude!, longitude: ProductData.shared.longitude!), span: MKCoordinateSpan(latitudeDelta: 0.1, longitudeDelta: 0.1))
self.mapView.setRegion(region, animated: true)
}
public func editCoord() {
performSegue(withIdentifier: "editCoord", sender: CustomCalloutView.self)
}
#IBAction func relocateButtonClicked(_ sender: Any) {
addPin()
}
#IBAction func finishedLocateButtonClicked(_ sender: Any) {
performSegue(withIdentifier: "finishedLocateSegue2", sender: self)
}
//4
func mapView(_ mapView: MKMapView, didDeselect view: MKAnnotationView) {
if view.isKind(of: CustomCalloutView.self ) || view.isKind(of: AnnotationView.self) || view.isKind(of: ProductAnnotation.self) {
return
} else {
customCallout?.removeFromSuperview()
}
}
//3
func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
if view.annotation is MKUserLocation {
return
}
//this creates the callout
let views = Bundle.main.loadNibNamed("CustomCalloutView", owner: nil, options: nil)
let calloutView = views?[0] as! CustomCalloutView
calloutView.delegate = self
calloutView.lngTitleLabel.text = "Lng"
calloutView.latTitleLabel.text = "Lat"
calloutView.lngTextField.text = String(format:"%f", ProductData.shared.longitude!)
calloutView.latTextField.text = String(format:"%f", ProductData.shared.latitude!)
calloutView.latTextField.layer.borderWidth = 0.0
calloutView.lngTextField.layer.borderWidth = 0.0
calloutView.latTextField.isEnabled = false
calloutView.lngTextField.isEnabled = false
calloutView.latTextField.keyboardType = .numberPad
calloutView.lngTextField.keyboardType = .numberPad
calloutView.alpha = 1.0
calloutView.layer.cornerRadius = 8
calloutView.center = CGPoint(x: view.bounds.size.width / 2, y: -calloutView.bounds.size.height*0.52)
customCallout = calloutView
view.addSubview(calloutView)
mapView.setCenter((view.annotation?.coordinate)!, animated: true)
}
//2
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if annotation is MKUserLocation {
return nil
}
var annotationView = self.mapView.dequeueReusableAnnotationView(withIdentifier: "Pin")
if annotationView == nil{
annotationView = AnnotationView(annotation: annotation, reuseIdentifier: "Pin")
annotationView?.isDraggable = true
annotationView?.canShowCallout = false
} else {
annotationView?.annotation = annotation
}
annotationView?.image = UIImage(named: "dot")
return annotationView
}
func saveButtonTapped() {
customCallout?.removeFromSuperview()
}
}
extension LocateVC: CustomCalloutViewDelegate {
func didClickEditButton() {
editCoord()
}
func didClickSaveButton() {
saveButtonTapped()
}
}
and here my custom callout:
class CustomCalloutView: UIView {
#IBOutlet weak var latTitleLabel: UILabel!
#IBOutlet weak var lngTitleLabel: UILabel!
#IBOutlet weak var editButton: UIButton!
#IBOutlet weak var saveButton: UIButton!
#IBOutlet weak var latTextField: UITextField!
#IBOutlet weak var lngTextField: UITextField!
var delegate: CustomCalloutViewDelegate?
var isEditing: Bool = false
#IBAction func didClickEditButton(_ sender: Any) {
// delegate?.didClickEditButton()
isEditing = true
latTextField.layer.borderWidth = 1.0
lngTextField.layer.borderWidth = 1.0
latTextField.isEnabled = true
lngTextField.isEnabled = true
saveButton.isHidden = false
}
#IBAction func saveButtonTapped(_ sender: Any) {
if isEditing == true {
if let lat = latTextField.text {
ProductData.shared.latitude = Double(lat)
}
if let lng = lngTextField.text {
ProductData.shared.longitude = Double(lng)
}
latTextField.layer.borderWidth = 0.0
lngTextField.layer.borderWidth = 0.0
latTextField.isEnabled = false
lngTextField.isEnabled = false
self.saveButton.setTitle("Save", for: .normal)
isEditing = false
} else {
self.saveButton.setTitle("Cancel", for: .normal)
delegate?.didClickSaveButton()
}
}
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
if self.bounds.contains(point) {
return true
} else {
return self.subviews.contains { $0.frame.contains(point) }
}
}
}
protocol CustomCalloutViewDelegate {
func didClickEditButton()
func didClickSaveButton()
}
any idea how i can achive that? Maybe in a general way.
Thank you in advance
Here's a link to DSCenterPinMapView. A CocoaPod I recommend you to use.
It is a custom MapView with an animated and customizable center pin useful for selecting locations in map.
Here is also a guide on installing CocoaPods if it is new to you.
You should install the Pod an then, as a solution to your questions:
Implement the delegate so that you can get the location where pin drops.
pinMapView.delegate = self
extension MyViewController: DSCenterPinMapViewDelegate {
func didStartDragging() {
// My custom actions
}
func didEndDragging() {
// My custom actions
selectedLocation = pinMapView.mapview.centerCoordinate
// Update Text field
}
}
After you finish adding the coordinates on your TextFields you should call
pinMapView.center(on coordinate: myTextFieldCoordinate)
to center the map on the desired location.
After changing the marker position get coordinates like
let latitude = marker.coordinate.latitude
let longitude = marker.coordinate.longitude
And to set coordinate
let coordinate = CLLocationCoordinate2D(latitude: "your lat", longitude: "your long")
marker.coordinate = coordinate
mapView.setCenter(coordinate, animated: true)
if you not keeping the marker reference then
guard let marker = self.appleMap.annotations.first else {return}
let latitude = marker.coordinate.latitude
let longitude = marker.coordinate.longitude
And to set coordinate
guard let marker = self.appleMap.annotations.first else {return}
let coordinate = CLLocationCoordinate2D(latitude: "your lat", longitude: "your long")
marker.coordinate = coordinate
mapView.setCenter(coordinate, animated: true)
Hope that will help.
Can any one help me to add different button action to the second annotation /pin (annotation2), Now the button do the same work in the two annotation pins how to do different work to each other . I'am using Swift3 in my project and this is my code . thanks
This is my code.
import UIKit
import MapKit
import CoreLocation
class MyAnnotation: MKPointAnnotation {
var uniqueId: Int!
}
class LocationViewController: UIViewController , MKMapViewDelegate , CLLocationManagerDelegate{
#IBOutlet weak var map: MKMapView!{
didSet{
map.delegate = self
}
}
#IBOutlet weak var locationInfo: UITextView!
override func viewDidLoad() {
super.viewDidLoad()
let locations = CLLocationCoordinate2DMake(33.314627, 44.303500)
let location2 = CLLocationCoordinate2DMake(33.312149, 44.3024567)
let span = MKCoordinateSpanMake(0.02, 0.02)
let span2 = MKCoordinateSpanMake(0.02, 0.02)
let region = MKCoordinateRegionMake(locations, span)
let region2 = MKCoordinateRegionMake(location2, span2)
map.setRegion(region, animated: true)
map.setRegion(region2, animated: true)
let annotation = MyAnnotation()
//annotation.setCoordinate(location)
annotation.coordinate = locations
annotation.title = "Zaid Homes"
annotation.subtitle = "Hay aljameaa"
annotation.uniqueId = 1
map.addAnnotation(annotation)
let annotation2 = MyAnnotation()
//annotation.setCoordinate(location)
annotation2.coordinate = location2
annotation2.title = "Zaid "
annotation2.subtitle = "aljameaa"
annotation.uniqueId = 2
map.addAnnotation(annotation2)
//Showing the device location on the map
self.map.showsUserLocation = true;
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
var view = mapView.dequeueReusableAnnotationView(withIdentifier: "AnnotationView Id")
if view == nil{
view = MKPinAnnotationView(annotation: annotation, reuseIdentifier: "AnnotationView Id")
view!.canShowCallout = true
} else {
view!.annotation = annotation
}
view?.leftCalloutAccessoryView = nil
view?.rightCalloutAccessoryView = UIButton(type: UIButtonType.detailDisclosure)
return view
}
func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
if (control as? UIButton)?.buttonType == UIButtonType.detailDisclosure {
mapView.deselectAnnotation(view.annotation, animated: false)
if let myAnnotation = view.annotation as? MyAnnotation {
if (myAnnotation.uniqueId == 1) {
performSegue(withIdentifier: "info", sender: view)
}
else {
performSegue(withIdentifier: "info2", sender: view)
}
}
}
}
}
The simplest way to know on which annotation you tap is using creating custom annotation class and adding annotation of it. So create one annotation class MyAnnotation child class of MKPointAnnotation and maintain one uniqueId with your multiple annotation.
class MyAnnotation: MKPointAnnotation {
var uniqueId: Int!
}
Now you need to add annotation of type MyAnnotation instead of MKPointAnnotation.
let annotation = MyAnnotation()
annotation.coordinate = locations
annotation.title = "Zaid Homes"
annotation.subtitle = "Hay aljameaa"
//Set uniqueId for annotation
annotation.uniqueId = 1
map.addAnnotation(annotation)
let annotation2 = MyAnnotation()
annotation2.coordinate = location2
annotation2.title = "Zaid "
annotation2.subtitle = "aljameaa"
//Set uniqueId for annotation
annotation2.uniqueId = 2
map.addAnnotation(annotation2)
Now check this uniqueId in calloutAccessoryControlTapped method on which annotation you tapped.
func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
if (control as? UIButton)?.buttonType == UIButtonType.detailDisclosure {
mapView.deselectAnnotation(view.annotation, animated: false)
if let myAnnotation = view.annotation as? MyAnnotation {
if (myAnnotation.uniqueId == 1) {
performSegue(withIdentifier: "info1", sender: view)
}
else {
performSegue(withIdentifier: "info2", sender: view)
}
}
}
}
you can do this by creating two subClass of MKPointAnnotation and then in the delegate's method you can do this :
func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
if view is subClass1 {
// do action for subclass 1
}
else if view is subClass2 {
// do action for subClass 2
}
}
Please let me know if this resolve your problem.
Update
you can make the implementation of you delegate more simpler like this exemple :
class ClassA:MKPointAnnotation{
func doActionWhenCalloutTapped(){
//do some action
}
}
class ClassB:ClassA{
override func doActionWhenCalloutTapped(){
//do some actions for annotation of type B
}
}
class ClassC:ClassA{
override func doActionWhenCalloutTapped(){
//do some actions for annotation of type C
}
}
func viewDidLoad(){
super.viewDidLoad()
let annotation = ClassB()
//annotation.setCoordinate(location)
annotation.coordinate = locations
annotation.title = "Zaid Homes"
annotation.subtitle = "Hay aljameaa"
map.addAnnotation(annotation)
let annotation2 = ClassC
//annotation.setCoordinate(location)
annotation2.coordinate = location2
annotation2.title = "Zaid "
annotation2.subtitle = "aljameaa"
map.addAnnotation(annotation2)
}
func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
(view.annotation as! ClassA).doActionWhenCalloutTapped()
}
I'm struggling with passing data from a map pin to a new vc.
Scenario
Map pin data (name, subtitle & coordinates) are currently being read from a JSON file. Map pins are dropped, when map pin has been clicked a new view will open and display the corresponding title and subtitle and some other data in labels in a new vc.
I've been following this tutorial for extracting data from a JSON file.
Issue: I'm struggling to find a way to pass the data from the map pin to the labels.
I've done a previous project where I pass data from one textfield to a label.
Thank you very much!
EDIT:
I realised I didn't give any code.
newFeatureVC
// Callout accessory
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
let identifier = "POIAnnotations"
if annotation is POIAnnotations {
var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: identifier)
if annotationView == nil {
annotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: identifier)
annotationView!.canShowCallout = true
let button = UIButton(type: .detailDisclosure)
annotationView!.rightCalloutAccessoryView = button
}
else {
annotationView!.annotation = annotation
}
return annotationView
}
return nil
}
func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
if control == view.rightCalloutAccessoryView {
performSegue(withIdentifier: "showAnnotationInfo", sender: self)
}
}
func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == "showAnnotationInfo" {
let destViewController = segue.destination as! ShopDetailViewController
}
}
POIAnnotations
This class is where variables stored for the name, subtitle and coordinates.
class POIAnnotations: NSObject, MKAnnotation {
var title: String?
var subtitle: String?
var coordinate: CLLocationCoordinate2D
init(title:String, subtitle:String, coordinate:CLLocationCoordinate2D) {
self.title = title
self.subtitle = subtitle
self.coordinate = coordinate
super.init()
}
class func fromJSON(_ json: [JSONValue]) -> POIAnnotations? {
// 1
var title: String
if let titleOrNil = json[1].string {
title = titleOrNil
} else {
title = ""
}
var subtitle: String
if let subtitleOrNil = json[2].string {
subtitle = subtitleOrNil
} else {
subtitle = ""
}
// 2
let latitude = (json[3].string! as NSString).doubleValue
let longitude = (json[4].string! as NSString).doubleValue
let coordinate = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
// 3
return POIAnnotations(title: title, subtitle: subtitle, coordinate: coordinate)
}
}
SecondVC
class ShopDetailViewController: UIViewController {
#IBOutlet weak var shopName: UILabel!
#IBOutlet weak var shopRating: UILabel!
#IBOutlet weak var cancelButton: UIBarButtonItem!
var shopNameData = "name"
var shopRatingData = "rating"
What I've already tried doing is the same way that I got the data from the JSON file in the POIAnnotations class.
I tried calling the fromJSON function then tried storing it in variable to display on the label. But I couldn't get my head around how to do it.
Use MKMapViewDelegate method to detect which pin is tapped and then display its data in view controller.
func mapView(MKMapView, didSelect: MKAnnotationView)
I have created the following:
let artworkPin = Artwork(title:"Wind Wand",locationName:"Majestic",discipline:"Statue",
coordinate:windwandcoord)
where Artwork refers to a class located in Artwork.swift, I am trying to assign a label to obtain the title value (Located in a annotation on UI View 1 ) through a Segue to go to a Label ( Located in UI View 2) by doing the following:
#IBOutlet weak var art_title: UILabel!
var viaSegue = "artwork title should be here"
override func viewDidLoad() {
super.viewDidLoad()
art_title.text = viaSegue
but I don't know how to reference it correctly for via Segue to take the value of "title".
ENTIRE FILE:
import UIKit
import MapKit
import CoreLocation
class ViewController: UIViewController, MKMapViewDelegate,CLLocationManagerDelegate {
#IBOutlet weak var MapView: MKMapView!
let manager = CLLocationManager()
var artworkPin = Artwork!
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
//let location = locations[0]
//let span:MKCoordinateSpan = MKCoordinateSpanMake(0.02, 0.02)
//let myLocation:CLLocationCoordinate2D = CLLocationCoordinate2DMake(location.coordinate.latitude, location.coordinate.longitude)
}
override func viewDidLoad() {
super.viewDidLoad()
// tracking user's location
manager.delegate = self
manager.desiredAccuracy = kCLLocationAccuracyBest
manager.requestWhenInUseAuthorization()
manager.startUpdatingLocation()
// Setting up Map
let distanceSpan:CLLocationDegrees = 2000
MapView.setRegion(MKCoordinateRegionMakeWithDistance(CLLocationCoordinate2DMake(-39.0556253, 174.0752278), distanceSpan, distanceSpan), animated: true)
MapView.showsUserLocation = true
MapView.delegate = self
// artwork on map
let windwandcoord: CLLocationCoordinate2D = CLLocationCoordinate2DMake(-39.055961,174.072288)
artworkPin = Artwork(title:"Wind Wand",locationName:"Majestic",discipline:"Statue",
coordinate:windwandcoord)
MapView.addAnnotation(artworkPin)
}
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView?
{
if annotation is MKUserLocation {return nil}
let reuseId = "pin"
var pinView = mapView.dequeueReusableAnnotationView(withIdentifier: reuseId) as? MKPinAnnotationView
if pinView == nil {
pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
pinView!.canShowCallout = true
pinView!.animatesDrop = true
pinView!.calloutOffset = CGPoint(x: -5, y: 5)
let calloutButton = UIButton(type: .detailDisclosure)
pinView!.rightCalloutAccessoryView = calloutButton
pinView!.sizeToFit()
}
else {
pinView!.annotation = annotation
}
return pinView
}
func mapView(_ mapView: MKMapView, annotationView view: MKAnnotationView, calloutAccessoryControlTapped control: UIControl) {
if control == view.rightCalloutAccessoryView {
performSegue(withIdentifier: "no", sender:self)
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let ViewTwo = segue.destination as! ViewTwo
ViewTwo.artworkPin = self.artworkPin
}
}
Thanks for your help
In your vc B add:
var artworkpin: Artwork!
In your vc A:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let vcB = segue.destinationViewController as! vcB
vcB.artworkpin = self.artworkpin
}
after that in vc B viewDidLoad you can get the title by art_title.text = artworkpin.title
I am developing an app where the user has to mark a location on a map, and then save it. My app then archives it, and when the user wants to see that location, the app is supposed to retreive the location's coordinates, and add an annonation on the map if the coordinates exist. Here is the piece of code I created to display the information the user selected-
#IBOutlet var mapGestureRecognizer: UIGestureRecognizer!
var item: itemData?
// Item Outlets
#IBOutlet weak var itemInfoView: UIView!
#IBOutlet weak var itemNameTextField: UITextField!
#IBOutlet weak var itemDescriptionLabel: UITextView!
#IBOutlet weak var mapView: MKMapView!
// Item Location Outlets
#IBOutlet weak var itemLocationView: UIView!
#IBOutlet weak var itemLocationTextView: UITextView!
let dropPin = MKPointAnnotation()
override func viewDidLoad() {
super.viewDidLoad()
self.mapView.delegate = self
// Data loading
itemNameTextField.delegate = self
itemDescriptionLabel.delegate = self
itemLocationTextView.delegate = self
// Press recognizer
func mapViewFunc(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
let annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: "myAnnotationView")
// configure the view
return annotationView
}
if let item = item {
itemNameTextField.text = item.itemName
itemDescriptionLabel.text = item.itemDescription
itemLocationTextView.text = item.itemPlace
dropPin.coordinate = mapView.convert(item.mapPoint, toCoordinateFrom: mapView)
dropPin.title = "Location of \(item.itemName)"
mapView.addAnnotation(dropPin)
print("Set the location of item pin to \(String(describing: dropPin.coordinate))")
}
// Styles
itemInfoView.layer.cornerRadius = 3
itemInfoView.layer.shadowColor = UIColor(red:0/255.0, green:0/255.0, blue:0/255.0, alpha: 1.0).cgColor
itemInfoView.layer.shadowOffset = CGSize(width: 0, height: 1.75)
itemInfoView.layer.shadowRadius = 1.7
itemInfoView.layer.shadowOpacity = 0.45
itemLocationView.layer.cornerRadius = 3
itemLocationView.layer.shadowColor = UIColor(red:0/255.0, green:0/255.0, blue:0/255.0, alpha: 1.0).cgColor
itemLocationView.layer.shadowOffset = CGSize(width: 0, height: 1.75)
itemLocationView.layer.shadowRadius = 1.7
itemLocationView.layer.shadowOpacity = 0.45
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
let annotation = MKPointAnnotation()
//let point = mapView.convert(coordinate, toPointTo: overlayView)
func action(gestureRecognizer:UIGestureRecognizer){
if let item = item {
dropPin.coordinate = mapView.convert((item.mapPoint), toCoordinateFrom: mapView)
dropPin.title = "Location of \(item.itemName)"
mapView.addAnnotation(dropPin)
print("Set the location of item pin to \(String(describing: dropPin.coordinate))")
}
else {
let itemName = itemNameTextField.text
let touchPoint = gestureRecognizer.location(in: mapView)
let newCoordinates = mapView.convert(touchPoint, toCoordinateFrom: mapView)
annotation.coordinate = newCoordinates
annotation.title = "Location of \(itemName!)"
mapView.addAnnotation(annotation)
}
}
#IBAction func mapLocationPress(_ sender: UILongPressGestureRecognizer) {
action(gestureRecognizer: mapGestureRecognizer)
}
All the print statements I've created work, so I know that the app does save the coordinates, and that it does convert them properly. However, when the app loads the information in the if let item = item portion of the viewDidLoad, the pin isn't dropped onto the map like it's supposed to.
Does anybody see why my code isn't working the way it's supposed to? Thanks!
If you need my full code, tell me, and I will put it into my question.
You need to use
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
let annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: "myAnnotationView")
// configure the view
return annotationView
}
outside your viewDidLoad() function
You should put mapViewFunc out of viewDidLoad, but if you want to leave it in viewDidLoad
try
func viewDidLoad() {
super.viewDidLoad()
DispatchQueue.main.async {
// add pin
}
}