The idea is simple. I have an array of StopData() which a custom struct I created to display different locations a mapView by doing a for each loop. My code looks a little like this:
var route = [StopData]()
struct StopData {
var addr: String?
var coord: CLLocationCoordinate2D?
var number: Int?
var completed = false
}
func addStopsToMap() {
mapView.removeAnnotations(mapView.annotations)
for stop in route {
let annotation = MKPointAnnotation()
annotation.coordinate = stop.coord!
annotation.title = "\(stop.number!)"
annotation.subtitle = stop.addr
mapView.addAnnotation(annotation)
}
}
func attemptLocationAccess() {
// For use in foreground
self.locationManager.requestWhenInUseAuthorization()
if CLLocationManager.locationServicesEnabled() {
locationManager.delegate = self
locationManager.desiredAccuracy = kCLLocationAccuracyBest
locationManager.startUpdatingLocation()
}
}
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
return NonClusteringAnnotation(annotation: annotation, reuseIdentifier: "NonClusteringAnnotation")
}
// MARK: - Location manager functions
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
return
}
func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
locationManager.requestWhenInUseAuthorization()
}
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
guard status == .authorizedWhenInUse else {
return
}
manager.requestLocation()
}
I also have a custom class like the following:
class NonClusteringAnnotation: MKMarkerAnnotationView {
override var annotation: MKAnnotation? {
willSet {
displayPriority = .required
}
}
}
I have three main things I would like to accomplish.
With this code, every pin is shown on the map and does not cluster. However, that also includes the current location blue dot which appears as a red pin like the rest of all the annotations. So I was wondering how can I make multiple custom annotation views and assign them only certain annotations whilst still retaining the blue dot indicating the users current location?
What I tried so far is adding a Boolean variable like willUseCustomAnnotation which would trigger a different return value like this:
func addStopsToMap() {
mapView.removeAnnotations(mapView.annotations)
willUseCustomAnnotation = true
for stop in route {
let annotation = MKPointAnnotation()
annotation.coordinate = stop.coord!
annotation.title = "\(stop.number!)"
annotation.subtitle = stop.addr
mapView.addAnnotation(annotation)
}
willUseCustomAnnotation = false
}
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
if willUseCustomAnnotation {
return NonClusteringAnnotation(annotation: annotation, reuseIdentifier: "NonClusteringAnnotation")
} else {
return nil
}
}
This does not work though because I presume it first adds all the annotations to mapview and then creates the view for them all at once.
I read on forums to change the view for the annotation you must create your own view in the viewForAnnotation function however that is only if you want a single custom view and not multiple custom view like I want. I'm new to MapKit so help will be really appreciated.
It's been a long time since I've used an MKMapView and custom annotations (it was in Objective-C.)
I seem to remember that in your mapView(_:viewFor:)
function you need to test to see if the annotation being passed to you is an MKUserLocation. If it is, return nil:
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
guard !annotation is MKUserLocation else {
//This is the user location. Return nil so the system uses the blue dot.
return nil
}
//Your code to create an return custom annotations)
}