I have to change image of my pin annotation in MapKit. And there should be two pin. One of these should be current location, second one is selector new location
func mapView(\_ mapView: MKMapView, viewFor annotation: MKAnnotation) -\> MKAnnotationView? {
if annotation is MKUserLocation {
return nil
}
let annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: "customannotation")
annotationView.image = UIImage(named:"pin")
annotationView.canShowCallout = true
return annotationView
}
func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
print("annotation title == \(String(describing: view.annotation?.title!))")
}
CodePudding user response:
You said:
I have to change image of my pin annotation in MapKit.
If you are saying that you have an annotation showing its associated annotation view on the map, and you want to change the image for that annotation view, you can add a property to your annotation to indicate which image is to be shown, and then have a custom MKAnnotationView
object which observes the annotation’s property and updates its image
, accordingly.
For example, consider an annotation that has an imageName
property:
class CustomAnnotation: MKPointAnnotation {
@objc dynamic var imageName: String
init(
coordinate: CLLocationCoordinate2D,
title: String? = nil,
subtitle: String? = nil,
imageName: String
) {
self.imageName = imageName
super.init()
self.coordinate = coordinate
self.title = title
self.subtitle = subtitle
}
}
Note, I made that an @objc dynamic
property so that I can have an annotation view that observes that image name change:
class CustomAnnotationView: MKAnnotationView {
static let reuseIdentifier = "CustomAnnotationView"
override var annotation: MKAnnotation? {
didSet { addObserver(for: annotation) }
}
override init(annotation: MKAnnotation?, reuseIdentifier: String?) {
super.init(annotation: annotation, reuseIdentifier: reuseIdentifier)
addObserver(for: annotation)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
var observer: NSKeyValueObservation?
func addObserver(for annotation: MKAnnotation?) {
let annotation = annotation as? CustomAnnotation
let imageName = annotation?.imageName ?? "red"
updateImage(named: imageName)
observer = annotation?.observe(\.imageName) { [weak self] annotation, _ in
self?.updateImage(named: annotation.imageName)
}
}
private func updateImage(named name: String) {
let image = UIImage(named: name)
self.image = image
// the following is only needed if you want the bottom of the
// image over the coordinates (e.g., you are using a “pin”).
if let image = image {
centerOffset = CGPoint(x: 0, y: -image.size.height / 2)
}
}
}
So, you can create the annotation:
let annotation = CustomAnnotation(coordinate: coordinate, imageName: "red")
mapView.addAnnotation(annotation)
And when you want, you can update the imageName
associated for that annotation, and the annotation view will observe that value change, and update the image accordingly:
annotation.imageName = "black"
That yields:
And there should be two pin. One of these should be current location, second one is selector new location
There is a special annotation for the user location, the MKUserLocation
. Right now, your mapView(_:viewFor:)
is returning nil
for this annotation. Just change your viewFor
to return whatever annotation you want for the MKUserLocation
rather than nil
.
Obviously this assumes (a) that you have enabled showsUserLocation
property for your mapView and (b) that you have requested permission for the user’s location. E.g.:
private let manager = CLLocationManager()
override func viewDidLoad() {
super.viewDidLoad()
if manager.authorizationStatus == .notDetermined {
manager.requestWhenInUseAuthorization()
}
mapView.showsUserLocation = true
...
}
And of course, set the appropriate privacy strings in Info.plist
:
CodePudding user response:
Once I had Faced the same issue... So I i used a for loop for this, In your case you can apply array for two pins or separate pin. Otherwise If you want to apply pins for multiple location at a same time than you do this by this logic.
Here's My code For Multiple pin
func showCurrentLocationOnMap(){
for data in location
{
for address in data.address {
let marker = GMSMarker()
let markerLocation = CLLocationCoordinate2D(latitude: address.latitude, longitude: address.longitude)
print("location: \(location)")
let view = Bundle.main.loadNibNamed("Mapview", owner: self, options: nil)?.first as! Mapview
let backImage = UIImage(named: "ic_map_pin")
view.outerPinImage.image = backImage
let urlString = data.business_logo.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
view.innerPinImage.sd_setImage(with: URL(string: urlString!), completed: nil)
print(view.innerPinImage!)
marker.title = data.business_name
marker.snippet = "View Details"
marker.position = markerLocation
marker.appearAnimation = GMSMarkerAnimation.pop
DispatchQueue.main.async {
view.innerPinImage.layer.cornerRadius = view.innerPinImage.frame.height/2
marker.iconView = view
}
marker.map = mapView
mapView.camera = GMSCameraPosition.camera(withLatitude: address.latitude, longitude: address.longitude, zoom: 15.0)
}
}
}
You can Call this Function in Your View ForAnnotaion Mapview Method