I want to use a custom XIB to use instead of MKAnnotation View, but I can't find any sources online that can help me. To be clear, I don't want a callout, I don't want an image in place of the pin, I want to replace the pin completely with an xib. For reference, I want my pins to look something like this -
https://i.sstatic.net/gbdFI.png
This would be the pin design, with the image in the middle changing for all the users. I've never worked on MKMapView and I've just displayed MKPinAnnotationView on the map after watching some tutorials about it. Can anybody please guide me on how to achieve this
EDIT: Using Alexander Nikolaychuk's link, I was able to create MKPinAnnotationViews using a XIB.
For reference, here is the code that worked for me :
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
// Don't want to show a custom image if the annotation is the user's location.
if (annotation is MKUserLocation) {
return nil
} else {
let annotationIdentifier = "CustomPinAnnotation"
let nibName = "CustomPinAnnotation"
let viewFromNib = Bundle.main.loadNibNamed(nibName, owner: self, options: nil)?.first as! CustomPinAnnotation
var annotationView: CustomPinAnnotation?
// if there is a view to be dequeued, use it for the annotation
if let dequeuedAnnotationView = mapView.dequeueReusableAnnotationView(withIdentifier: annotationIdentifier) as? CustomPinAnnotation {
if dequeuedAnnotationView.subviews.isEmpty {
dequeuedAnnotationView.addSubview(viewFromNib)
}
annotationView = dequeuedAnnotationView
annotationView?.annotation = annotation
} else {
// if no views to dequeue, create an Annotation View
let av = CustomPinAnnotation(annotation: annotation, reuseIdentifier: annotationIdentifier)
av.addSubview(viewFromNib)
annotationView = av // extend scope to be able to return at the end of the func
}
// after we manage to create or dequeue the av, configure it
if let annotationView = annotationView {
annotationView.canShowCallout = true // callout bubble
annotationView.rightCalloutAccessoryView = UIButton(type: .detailDisclosure)
annotationView.frame = CGRect(x: 0, y: 0, width: 40, height: 40)
let customView = annotationView.subviews.first as! CustomPinAnnotation
customView.frame = annotationView.frame
customView.profilePicImageView.image = UIImage(named: "dummy4")
}
return annotationView
}
}
Now, there are 2 issues left in my app
I have all the data that I want to show on the map in an array modal. How can I use the profile picture URL from my modal and display it onto the imageView in the annotation View? Since viewFor annotation does not iterate and doesn't have any index value, its challenging for me to pass my modal here.
Even though my xIB looks like this : https://i.sstatic.net/Wg4ZU.png
It looks like this on the MapView: https://i.sstatic.net/e7CAr.jpg
func mapView(_ mapView: MKMapView, viewFor annotation: MKAnnotation) -> MKAnnotationView? {
// Don't want to show a custom image if the annotation is the user's location.
if (annotation is MKUserLocation) {
return nil
} else {
let annotationIdentifier = "AnnotationIdentifier"
var annotationView: MKPinAnnotationView?
if let dequeuedAnnotationView = mapView.dequeueReusableAnnotationView(withIdentifier: "AnnotationIdentifier") as? MKPinAnnotationView {
//Here you can setup
annotationView = dequeuedAnnotationView
annotationView?.annotation = annotation
}
}
You don't need to initialize in on your own. It uses a custom CollectionViewCells. Try to use this example. (This is a delegate function FYI)