Dmitriy Lupych
Dmitriy Lupych

Reputation: 639

MKMapAnnotationView - how to support dark mode in Swift

I have Apple's mapView and custom markers displayed in it. Each marker has 2 images in Assets for the dark and light mode appropriately. The problem is that markers do not react to the dark/light mode theme changes. What I've tried:

SO, how can I update markers when the theme changes?

Upvotes: 1

Views: 652

Answers (1)

MattG
MattG

Reputation: 41

I've just found the same thing, so I've modified my MKAnnotationView-derived class to handle it:

class MapPinView: MKAnnotationView {
    
    // MKAnnotationView doesn't seem to automatically use the correct image for dark mode, so we have to ensure it does
    var combinedImage: UIImage? {
        didSet {
            updateImage()
        }
    }

    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)
        
        if let imageName = selected ? "pushPinSelected" : "pushPin",
            let image = UIImage(named: imageName) {
            self.combinedImage = image
        }
    }
    
    override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
        super.traitCollectionDidChange(previousTraitCollection)
        if traitCollection.userInterfaceStyle != previousTraitCollection?.userInterfaceStyle {
            updateImage()
        }
    }
    
    private func updateImage() {
        image = combinedImage?.imageAsset?.image(with: traitCollection) ?? combinedImage
        if let image = self.image {
            centerOffset = CGPoint(x: 0.0, y: -image.size.height / 2.0)
        }
    }

}

Note that I also initialise the combinedImage, when creating the MapPinView:

extension MapView: MKMapViewDelegate {
    
    func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {    
        let annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: Constants.annotationId, for: annotation) as! MapPinView
        annotationView.combinedImage = UIImage(named: "pushPin")            
        return annotationView
    }
...

Upvotes: 4

Related Questions