I am creating a MapView where I want to display some custom Annotations.
So I think usually what you do is add some IMKAnnotation
to the MKMapView
using the AddAnnotation
method. I make sure to invoke that on the main thread like:
new NSObject().InvokeOnMainThread(() => {
_mapView.AddAnnotation(myNewAnnotation);
});
After these I are added I do see that the MKMapView
now contains all the annotations I added in the Annotations
property when inspecting with the debugger.
However, the problem is that GetViewForAnnotation
is never invoked, no matter how I do it.
I've tried:
_mapView.GetViewForAnnotation += ViewForAnnotation;
private MKAnnotationView ViewForAnnotation(MKMapView mapView, IMKAnnotation annotation) {
// do stuff here
}
I've tried implementing my own delegate:
public class MyMapViewDelegate : MKMapViewDelegate
{
public override MKAnnotationView GetViewForAnnotation(MKMapView mapView, IMKAnnotation annotation) {
// do stuff
}
}
_delegate = new MyMapViewDelegate();
_mapView.Delegate = _delegate;
I've tried using WeakDelegate
:
public class MapView : ViewController, IMKMapViewDelegate
{
private MKMapView _mapView;
public override void ViewDidLoad() {
_mapView = new MKMapView();
_mapView.WeakDelegate = this;
}
[Export("mapView:viewForAnnotation:")]
public MKAnnotationView GetViewForAnnotation(MKMapView mapView, IMKAnnotation annotation) {
// do stuff
}
}
Nothing seems to trigger the GetViewForAnnotation
method. Any ideas what I do wrong?
EDIT:
A bit more details what I have now.
[Register("MapView")]
public class MapView : MvxViewController<MapViewModel>
{
private MKMapView _mapView;
private NMTAnnotationManager _annotationManager;
public override void ViewDidLoad()
{
base.ViewDidLoad();
_mapView = new MKMapView();
_mapView.GetViewForAnnotation += GetViewForAnnotation;
_annotationManager = new NMTAnnotationManager(_mapView);
var bindSet = this.CreateBindingSet<MapView, MapViewModel>();
bindSet.Bind(_annotationManager).For(a => a.ItemsSource).To(vm => vm.Locations).OneWay();
bindSet.Apply();
Add(_mapView);
View.SubviewsDoNotTranslateAutoresizingMaskIntoConstraints();
View.AddConstraints(
_mapView.AtTopOf(View),
_mapView.AtLeftOf(View),
_mapView.AtRightOf(View),
_mapView.AtBottomOf(View));
}
private MKAnnotationView GetViewForAnnotation(MKMapView mapview, IMKAnnotation annotation)
{
return null;
}
}
The NMTAnnotationManager
simply weak subscribes to the INotifyCollectionChanged
event the ObservableCollection
which is used as ItemsSource
in the binding. When the collection changes it simply adds and removes the Annotations from the MKMapView
, nothing magical happens here. I have verified that it does indeed add, in this case 13, different IMKAnnotation
instances to the MKMapView
and they can be inspected in the Annotations
property of it.
So as @Philip suggested in his answer, GetViewForAnnotation
does get set before Annotations are added to the MapView. But if I put a breakpoint or some trace in the method it never gets hit.
The same code above, just with a simple MKMapViewDelegate
like so:
public class MyMapViewDelegate : MKMapViewDelegate
{
public override void MapLoaded(MKMapView mapView)
{
Mvx.Trace("MapLoaded");
}
public override MKAnnotationView GetViewForAnnotation(MKMapView mapView, IMKAnnotation annotation)
{
Mvx.Trace("GetViewForAnnotation");
return null;
}
}
Does not work either. Although, the MapLoaded
event gets hit for each time the map is rendered, but why does GetViewForAnnotation
not get hit?
OK, so apparently the problem was PEBKAC.
The annotation indeed got added to the MKMapView
. However, none of them had their Coordinate
property set. So obviously the map did not know where to present them and never called GetViewForAnnotation
.