How to make a custom MKAnnotationView with XIB
UPDATED CODE BASED ON Sh-Khan's answer
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"
let nibName = "MyAnnotationView"
let viewFromNib = Bundle.main.loadNibNamed(nibName, owner: self, options: nil)?.first as! MyAnnotationView
var annotationView: MyAnnotationView?
// if there is a view to be dequeued, use it for the annotation
if let dequeuedAnnotationView = mapView.dequeueReusableAnnotationView(withIdentifier: annotationIdentifier) as? MyAnnotationView {
if dequeuedAnnotationView.subviews.isEmpty {
dequeuedAnnotationView.addSubview(viewFromNib)
}
annotationView = dequeuedAnnotationView
annotationView?.annotation = annotation
} else {
// if no views to dequeue, create an Annotation View
let av = MyAnnotationView(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! MyAnnotationView
customView.frame = annotationView.frame
customView.textLabel.text = (annotationView.annotation?.title)!
}
return annotationView
}
}
How to use a custom XIB for MKAnnotationView?
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)
How to add a customView xib as annotation in Ios?
Try to add the object of the nib view to the annotation view like this
func mapView(_ mapView: MKMapView,viewFor annotation: MKAnnotation) -> MKAnnotationView?
{
if annotation is MKUserLocation == true
{
return nil
}
let senderAnnotation = annotation as! MyAnnotation
let pinReusableIdentifier = senderAnnotation.pinColor.rawValue
var annotationView = mapView.dequeueReusableAnnotationView(withIdentifier: pinReusableIdentifier)
if annotationView == nil
{
annotationView = MKAnnotationView(annotation: senderAnnotation, reuseIdentifier: pinReusableIdentifier)
annotationView!.canShowCallout = true
}
let customView = (Bundle.main.loadNibNamed("directOrderView", owner: self, options: nil))?[0] as! directOrderView;
var calloutViewFrame = customView.frame;
calloutViewFrame.origin = CGPoint(x:-calloutViewFrame.size.width/2 + 30,y: -calloutViewFrame.size.height);
customView.frame = calloutViewFrame;
annotationView?.addSubview(customView)
return annotationView
}
Custom callout view with xib
In didSelectAnnotationView
load xib from bundle and add subview to the annotation view. here CustomXibCallout is xib file and CustomCalloutView is MKAnnotationView.
func mapView(mapView: MKMapView, didSelectAnnotationView view: MKAnnotationView) {
if view.annotation!.isKindOfClass(MKUserLocation){
return
}
//Custom xib
let customView = (NSBundle.mainBundle().loadNibNamed("CustomXibCallout", owner: self, options: nil))[0] as! CustomCalloutView;
let calloutViewFrame = customView.frame;
customView.frame = CGRect(x: -calloutViewFrame.size.width/2.23, y: -calloutViewFrame.size.height-7, width: 315, height: 200)
view.addSubview(customView)
}
in didDeselectAnnotationView
remove the added view
func mapView(mapView: MKMapView, didDeselectAnnotationView view: MKAnnotationView)
{
for childView:AnyObject in view.subviews{
childView.removeFromSuperview();
}
}
Example for CustomCallout
How to set .xib interface as a custom callout view?
you can show custom callout view like this in Swift.
func mapView(mapView: MKMapView!, didSelectAnnotationView view: MKPinAnnotationView!)
{
if view.annotation.isKindOfClass(MKUserLocation){
return
}
var customView = (NSBundle.mainBundle().loadNibNamed("SubView", owner: self, options: nil))[0] as CustomSubView;
var calloutViewFrame = customView.frame;
calloutViewFrame.origin = CGPointMake(-calloutViewFrame.size.width/2 + 15, -calloutViewFrame.size.height);
customView.frame = calloutViewFrame;
let cpa = view.annotation as CustomPointAnnotation
//You can add set vlaues for here
//cpa.title
//cpa.postCode
//cpa.street
view.addSubview(customView)
//zoom map to show callout
let spanX = 0.0000000000000001
let spanY = 0.0000000000000001
var newRegion = MKCoordinateRegion(center:cpa.coordinate, span: MKCoordinateSpanMake(spanX, spanY))
self.map?.setRegion(newRegion, animated: true)
}
Related Topics
Operation Not Permitted When Executing 'Killall' with Swift
Error: Extraneous Argument Label 'No1:' in Call
Characters Is Unavailable' Please Use String Directly
Swift: Generic Overloads, Definition of "More Specialized"
How, Exactly, Do I Render Metal on a Background Thread
Attributed Text, Replace a Specific Font by Another Using Swift
How to Convert Dispatchtimeinterval to Nstimeinterval (Or Double)
Take a Full Screenshot for All Webview in Swift
Why Is There a "Plus" Icon at the Top Right Corner of My View
Swift: For-In Loop Requires '[Deepspeechtokenmetadata]' to Conform to 'Sequence'
Handling an Attribute of an Xml Element in Swift
Why Use Float(Arc4Random())/0Xffffffff Instead of Drand()
How to Reduce the Opacity of the Shadows in Realitykit
Swift Firebase Check If User Exists
Decode Dictionary with Random Initial Key
How to Convert a Unsafemutablepointer<Void> to Uint8
Swift 1.2 Not Working with Same Function Name and Different Parameter