0
votes

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.

  • Show every annotation pin and not have it cluster
  • Show custom annotation if the variable completed is false
  • Show a different custom annotation if completed is true

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.

1

1 Answers

0
votes

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