简体   繁体   中英

Swift MKMapView Pin Annotation Issue

I'm trying to display pins on a map, with a preset search parameter. On a button click, the app displays all of the local taxi services. That part I have down...I have the items appending to an [MKPointAnnotation] , and it successfully displays a populated list in the tableView as well as pins on the mapView . For some reason I can't get the title and subtitle to display when you tap on the pin on the mapView , even when implementing the viewFor annotation: delegate. Any ideas?

class MapViewController: UIViewController, CLLocationManagerDelegate, UITableViewDataSource, UITableViewDelegate, MKMapViewDelegate {

@IBOutlet weak var mapView: MKMapView!
@IBOutlet weak var tableView: UITableView!

let locationManager = CLLocationManager()
let regionRadius: CLLocationDistance = 1500
var matchingItems: [MKMapItem] = [MKMapItem]()
var annotationGroup = [MKPointAnnotation]()

override func viewDidLoad() {
        super.viewDidLoad()
        locationManager.delegate = self
        tableView.delegate = self
        tableView.dataSource = self
        mapView.delegate = self


        tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
        tableView.allowsSelection = true


        let currentLocation = locationManager.location
        guard let latitude = currentLocation?.coordinate.latitude,
            let longitude = currentLocation?.coordinate.longitude else {
                alertPopup(title: "Enable Location Services", message: "Navigate to Settings >", buttonTitle: "Ok")
                return
        }
        let initialLocation = CLLocation(latitude: latitude, longitude: longitude)
        tabBarController?.tabBar.isHidden = true
        centerMapOnLocation(location: initialLocation)

        let request = MKLocalSearchRequest()
        request.naturalLanguageQuery = "Taxi"
        request.region = mapView.region

        let search = MKLocalSearch(request: request)

        search.start(completionHandler: {(response, error) in

            if error != nil {
                print("Error occured in search: \(error!.localizedDescription)")
            } else if response!.mapItems.count == 0 {
                print("No Matches Found")
            } else {
                print("Matches Found")
            }

            for location in response!.mapItems {
                print("Name = \(String(describing: item.name))")
                print("Phone = \(String(describing: item.phoneNumber))")
                self.matchingItems.append(item)

                var pinAnnotationView = MKPinAnnotationView()
                let annotation = MKPointAnnotation()
                annotation.coordinate.longitude = location.placemark.coordinate.longitude
                annotation.coordinate.latitude = location.placemark.coordinate.latitude
                annotation.title? = location.name!
                annotation.subtitle = location.phoneNumber!
                self.annotationGroup.append(annotation)
                self.mapView.addAnnotations(self.annotationGroup)
                pinAnnotationView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: nil)
                self.mapView.addAnnotation(pinAnnotationView.annotation!)
            }
            self.tableView.reloadData()
            print("Reloaded Table Data")
            print(self.matchingItems)
            self.mapView.showAnnotations(self.annotationGroup, animated: true)

        })
    }

func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {

        if !(annotation is MKUserLocation) {
            let pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: String(annotation.hash))

            let rightButton = UIButton(type: .contactAdd)
            rightButton.tag = annotation.hash

            pinView.animatesDrop = true
            pinView.canShowCallout = true
            pinView.rightCalloutAccessoryView = rightButton

            return pinView
        } else {
            print("Returned nil")
            return nil
        }

    }
}

The issue is the optional annotation.title? = location.name! annotation.title? = location.name! . Remove the optional and it works.

    for location in response!.mapItems {
        print("Name = \(String(describing: location.name))")
        print("Phone = \(String(describing: location.phoneNumber))")
        self.matchingItems.append(location)
        let annotation = MKPointAnnotation()
        annotation.coordinate.longitude = location.placemark.coordinate.longitude
        annotation.coordinate.latitude = location.placemark.coordinate.latitude
        annotation.title = location.name!  //This is the line to remove the optional annotation.title? from.
        annotation.subtitle = location.phoneNumber!
        self.annotationGroup.append(annotation)
        self.mapView.addAnnotations(self.annotationGroup)
        self.mapView.showAnnotations(self.annotationGroup, animated: true)
        }

Maybe is too late but anyway

First of all, MKAnnotation is a protocol so I think that you must define a custom class for your objects, and this class must implement this protocol or in this case we can define an extension for MKMapItem implementing MKAnnotation protocol

extension MKMapItem : MKAnnotation
{
  public var coordinate: CLLocationCoordinate2D {
    return self.placemark.coordinate
  }


  // Title and subtitle for use by selection UI.
  public var title: String? {
    return self.name
  }

  public var subtitle: String? {
    return self.phoneNumber
  }
}

with this your code will be reduced to this

search.start(completionHandler: {(response, error) in

            if error != nil {
                print("Error occured in search: \(error!.localizedDescription)")
            } else if response!.mapItems.count == 0 {
                print("No Matches Found")
            } else {
                print("Matches Found")
            }

            for location in response!.mapItems {
                print("Name = \(String(describing: item.name))")
                print("Phone = \(String(describing: item.phoneNumber))")
                self.matchingItems.append(item)
            }
          self.mapView.addAnnotations(self.matchingItems)
            self.tableView.reloadData()
            print("Reloaded Table Data")
            print(self.matchingItems)
            self.mapView.showAnnotations(self.matchingItems, animated: true)
        })

Once you have this then your implementation of func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {} func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {} should work

Hope this helps

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM