Issue
I am working on a MapView where on click of any custom annotation pin, I am showing custom callout view (load from xib file).
From this Custom Callout I have an UIButton, I already can detect click on this button but I want to access on the Map like the : view?.rightCalloutAccessoryView in the basic callout.
func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView, {
if view.annotation!.isKind(of: MKUserLocation.self){
return
}
let customView = (Bundle.main.loadNibNamed("CustomCalloutView", owner: self, options: nil))?[0] as! CustomCalloutView;
let calloutViewFrame = customView.frame;
customView.frame = CGRect(x: -calloutViewFrame.size.width/2.23, y: -calloutViewFrame.size.height+10, width: 315, height: 170)
view.addSubview(customView)
let region = MKCoordinateRegion(center: pinToZoomOn!.coordinate, span: span)
mapView.setRegion(region, animated: true)
}
The route is correctly calculated from the classic callout but I can't know how to access my map from the button of my custom callout.
My CustomCalloutViewClass :
import UIKit
import MapKit
class CustomCalloutView: MKAnnotationView {
@IBOutlet weak var goButton: UIButton!
@IBAction func goButton(_ sender: AnyObject) {
print("Button clicked sucessfully")
}
// MARK: - Detect taps on callout
override func hitTest(_ point: CGPoint, with event: UIEvent?) -> UIView? {
let hitView = super.hitTest(point, with: event)
if hitView != nil {
superview?.bringSubview(toFront: self)
}
return hitView
}
override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
let rect = self.bounds
var isInside = rect.contains(point)
if !isInside {
for view in subviews {
isInside = view.frame.contains(point)
if isInside {
break
}
}
}
return isInside
}
}
If someone have an idea it will be helpfull I'm stuck on this issue.
Thank you in advance.
Solution
Option 1: Capture a MKMapView instance in the closure passed to a CustomCalloutView
Add the closure which will be called on the button action. The closure will capture the MKMapView
instance and you will be able to us is inside.
class CustomCalloutView: MKAnnotationView {
var didTapGoButton: (() -> Void)?
@IBAction func goButton(_ sender: AnyObject) {
didTapGoButton?()
}
}
Option 2: Add a weak reference to MKMapView as a property of the callout
This is not a clean solution but it may be an option under some circumstances. You only have to create a weak property storing a reference to MKMapView
instance in CustomCalloutView
class CustomCalloutView: MKAnnotationView {
weak var mapView: MKMapView?
}
Configuration
This is how you can wire up the CustomCalloutView
for both solutions. Remember to use swift capture list to capture a weak reference to a MKMapView
instance. Without it you may create a strong reference cycle.
func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
// ...
let customView = (Bundle.main.loadNibNamed("CustomCalloutView", owner: self, options: nil))?[0] as! CustomCalloutView;
// Option 1
customView.didTapGoButton = { [weak mapView ] in
print(mapView?.annotations.count)
}
// Option 2
customView.mapView = mapView
// ...
}
Answered By - Kamil Szostakowski
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.