简体   繁体   中英

Set MapKit pins with different colors

I am new in iOS and I implemented a MapKit with static markers from different arrays types and they are working fine, I am trying to put pins that come from shops array to be blue for example, and pins that come from community read, etc.. I have no idea about how to do this at all, they are all in red in the map and my goal is to change the color for every array of pins

here what I have tried:

import UIKit
import MapKit

class myMapViewController: UIViewController, MKMapViewDelegate {

    var shops = [Shops]()
    var communities = [Community]()
    var cyclists = [Cyclist]()
    var circuits = [Circuit]()
    
    @IBOutlet weak var myMap: MKMapView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
       
        shops.append(Shops(id: 0, title: "Shop1", latitude: 36.553015 , longitude: 10.592774))
        shops.append(Shops(id: 0, title: "Shop2", latitude: 35.499414 , longitude: 10.824846))
        communities.append(Community(id: 0, title: "community1", latitude: 37.276943 , longitude: 10.934709 ))
        communities.append(Community(id: 0, title: "community2", latitude: 35.427828 , longitude: 9.748186 ))
        circuits.append(Circuit(id: 0, title: "circuit1", latitude: 33.773035 , longitude: 10.857805 ))
        cyclists.append(Cyclist(id: 0, title: "cyclist1", latitude: 35.785118 , longitude: 10.000871 ))
        createShopsAnnotations(locations: shops)
        createCircuitsAnnotations(locations: circuits)
        createCommunityAnnotations(locations: communities)
        createCyclistsAnnotations(locations: cyclists)
    }
    
    func createShopsAnnotations(locations:[Shops]){
        for location in locations {
            let annotations = MKPointAnnotation()
            annotations.title = location.title as? String
            annotations.coordinate = CLLocationCoordinate2D(latitude: location.latitude as! CLLocationDegrees , longitude: location.longitude as! CLLocationDegrees)
            myMap.addAnnotation(annotations)
        }
    }
        
    func createCircuitsAnnotations(locations:[Circuit]){
        for location in locations {
            let annotations = MKPointAnnotation()
            annotations.title = location.title as? String
            annotations.coordinate = CLLocationCoordinate2D(latitude: location.latitude as! CLLocationDegrees , longitude: location.longitude as! CLLocationDegrees)
            myMap.addAnnotation(annotations)
        }
    }
    
    func createCommunityAnnotations(locations:[Community]){
        for location in locations {
            let annotations = MKPointAnnotation()
            annotations.title = location.title as? String
            annotations.coordinate = CLLocationCoordinate2D(latitude: location.latitude as! CLLocationDegrees , longitude: location.longitude as! CLLocationDegrees)
            myMap.addAnnotation(annotations)
        }
    }
    
    func createCyclistsAnnotations(locations:[Cyclist]){
        for location in locations {
            let annotations = MKPointAnnotation()
            annotations.title = location.title as? String
            annotations.coordinate = CLLocationCoordinate2D(latitude: location.latitude as! CLLocationDegrees , longitude: location.longitude as! CLLocationDegrees)
            
            myMap.addAnnotation(annotations)
        }
    }
}

I have headed some tutorials but I was not able to apply them on my example.

The basic idea is to make an annotation view type to render the correct color. So, assume for a second that you have four annotation types (see below), then you might have an annotation view type like so:

class AnnotationView: MKMarkerAnnotationView {
    override var annotation: MKAnnotation? { didSet { update(for: annotation) } }

    override init(annotation: MKAnnotation?, reuseIdentifier: String?) {
        super.init(annotation: annotation, reuseIdentifier: reuseIdentifier)
        update(for: annotation)
    }

    required init?(coder: NSCoder) {
        super.init(coder: coder)
    }

    func update(for annotation: MKAnnotation?) {
        switch annotation {
        case is Shop: markerTintColor = .blue
        case is Community: markerTintColor = .cyan
        case is Cyclist: markerTintColor = .green
        case is Circuit: markerTintColor = .red
        default: break
        }
    }
}

And then you would have your view controller register that annotation view for your map view:

override func viewDidLoad() {
    super.viewDidLoad()

    mapView.register(AnnotationView.self, forAnnotationViewWithReuseIdentifier: MKMapViewDefaultAnnotationViewReuseIdentifier)

    ...
}

Note, when you register an annotation view type like this, you do not want to implement any mapView(_:viewFor:) method. Since iOS 11, that delegate method is not needed/recommended any more.

Anyway, that annotation view type assumes you have four types of annotations. I'd personally make Shop , Community , Cyclist and Circuit just be annotation types, eg

class Shop: NSObject, MKAnnotation {
    let id: Int
    dynamic var title: String?
    dynamic var subtitle: String?
    dynamic var coordinate: CLLocationCoordinate2D

    init(id: Int, title: String, subtitle: String? = nil, coordinate: CLLocationCoordinate2D) {
        self.id = id
        self.title = title
        self.subtitle = subtitle
        self.coordinate = coordinate

        super.init()
    }
}

// repeat for the other three types

And then, when I want to add them to my map:

shops.append(Shop(id: 0, title: "Shop1", coordinate: CLLocationCoordinate2D(latitude: 36.553015, longitude: 10.592774)))
shops.append(Shop(id: 0, title: "Shop2", coordinate: CLLocationCoordinate2D(latitude: 35.499414 , longitude: 10.824846)))
communities.append(Community(id: 0, title: "community1", coordinate: CLLocationCoordinate2D(latitude: 37.276943 , longitude: 10.934709)))
communities.append(Community(id: 0, title: "community2", coordinate: CLLocationCoordinate2D(latitude: 35.427828 , longitude: 9.748186)))
circuits.append(Circuit(id: 0, title: "circuit1", coordinate: CLLocationCoordinate2D(latitude: 33.773035 , longitude: 10.857805)))
cyclists.append(Cyclist(id: 0, title: "cyclist1", coordinate: CLLocationCoordinate2D(latitude: 35.785118 , longitude: 10.000871)))

mapView.addAnnotations(shops + communities + circuits + cyclists)

Alternatively, you might have one annotation type:

enum PlaceType {
    case shop, community, cyclist, circuit
}

class Place: NSObject, MKAnnotation {
    let id: Int
    let type: PlaceType
    dynamic var title: String?
    dynamic var subtitle: String?
    dynamic var coordinate: CLLocationCoordinate2D

    init(id: Int, type: PlaceType, title: String, subtitle: String? = nil, coordinate: CLLocationCoordinate2D) {
        self.id = id
        self.type = type
        self.title = title
        self.subtitle = subtitle
        self.coordinate = coordinate

        super.init()
    }
}

You'd then instantiate these places:

var places = [Place]()

override func viewDidLoad() {
    super.viewDidLoad()

    mapView.register(AnnotationView.self, forAnnotationViewWithReuseIdentifier: MKMapViewDefaultAnnotationViewReuseIdentifier)

    places = [
        Place(id: 0, type: .shop, title: "Shop1", coordinate: CLLocationCoordinate2D(latitude: 36.553015, longitude: 10.592774)),
        Place(id: 0, type: .shop, title: "Shop2", coordinate: CLLocationCoordinate2D(latitude: 35.499414 , longitude: 10.824846)),
        Place(id: 0, type: .community, title: "community1", coordinate: CLLocationCoordinate2D(latitude: 37.276943 , longitude: 10.934709)),
        Place(id: 0, type: .community, title: "community2", coordinate: CLLocationCoordinate2D(latitude: 35.427828 , longitude: 9.748186)),
        Place(id: 0, type: .circuit, title: "circuit1", coordinate: CLLocationCoordinate2D(latitude: 33.773035 , longitude: 10.857805)),
        Place(id: 0, type: .cyclist, title: "cyclist1", coordinate: CLLocationCoordinate2D(latitude: 35.785118 , longitude: 10.000871))
    ]
    mapView.addAnnotations(places)
}

And your annotation view type would then use this type parameter:

class AnnotationView: MKMarkerAnnotationView {
    override var annotation: MKAnnotation? { didSet { update(for: annotation) } }

    override init(annotation: MKAnnotation?, reuseIdentifier: String?) {
        super.init(annotation: annotation, reuseIdentifier: reuseIdentifier)
        update(for: annotation)
    }

    required init?(coder: NSCoder) {
        super.init(coder: coder)
    }

    func update(for annotation: MKAnnotation?) {
        guard let annotation = annotation as? Place else { return }

        switch annotation.type {
        case .shop: markerTintColor = .blue
        case .community: markerTintColor = .cyan
        case .cyclist: markerTintColor = .green
        case .circuit: markerTintColor = .red
        }
    }
}

This results in:

地图

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