Should I use MKAnnotation, MKAnnotationView or MKPinAnnotation?
I haven't used MonoTouch but the underlying SDK usage is the same as iOS I believe.
MKAnnotation
is the protocol/interface to base your annotation data model on. You could also use the pre-defined MKPointAnnotation
class (which implements the MKAnnotation
interface) for your annotation data model objects instead of creating a custom class if all you need is title
, subtitle
, and coordinate
.
MKAnnotationView
is how the annotation's view should appear and is set in the map view's viewForAnnotation
delegate method (not created inline). Annotation views can be re-used between multiple annotation objects that will have the same appearance (for example a pin image). So theoretically a single MKAnnotationView
instance might be used for multiple annotation objects that implement MKAnnotation
(assuming they are not all on the screen at once).
So you create an MKAnnotation
-based object and pass that in the addAnnotation
(ie. AddAnnotationObject
) call. Then in the viewForAnnotation
delegate method, you create and return an instance of an MKAnnotationView
-based object.
"MKPinAnnotation" (actually MKPinAnnotationView
) is a pre-defined subclass of MKAnnotationView
which provides a default pin image. You can return an instance of MKPinAnnotationView
in the viewForAnnotation
delegate method instead of designing a custom view.
The place where you would create the right callout accessory button is in the viewForAnnotation
delegate method. You create a UIButton
of type UIButtonTypeDetailDisclosure
and set it as the annotation view's rightCalloutAccessoryView
.
The button press would be handled in the map view's calloutAccessoryControlTapped
delegate method which provides a reference to the annotation view and annotation the callout is in.
The method names given are the ones in iOS but the names in MonoTouch should be similar.
MKPinAnnotationView versus MKAnnotationView
The pinView
variable is declared as an MKPinAnnotationView
but that line creates an MKAnnotationView
.
Change this line:
pinView=[[[MKAnnotationView alloc]initWithAnnotation...
to:
pinView=[[[MKPinAnnotationView alloc]initWithAnnotation...
You should also have an else
part to that if
to handle annotation view re-use:
else
pinView.annotation = annotation;
MKMapView: Instead of Annotation Pin, a custom view
When you want to use your own image for an annotation view, you should create an MKAnnotationView
instead of an MKPinAnnotationView
.
MKPinAnnotationView
is a subclass of MKAnnotationView
so it has an image
property but it generally overrides that and draws a pin image (that's what it's for).
So change the code to:
-(MKAnnotationView *)mapView:(MKMapView *)mV viewForAnnotation:(id <MKAnnotation>)annotation
{
MKAnnotationView *pinView = nil;
if(annotation != mapView.userLocation)
{
static NSString *defaultPinID = @"com.invasivecode.pin";
pinView = (MKAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:defaultPinID];
if ( pinView == nil )
pinView = [[MKAnnotationView alloc]
initWithAnnotation:annotation reuseIdentifier:defaultPinID];
//pinView.pinColor = MKPinAnnotationColorGreen;
pinView.canShowCallout = YES;
//pinView.animatesDrop = YES;
pinView.image = [UIImage imageNamed:@"pinks.jpg"]; //as suggested by Squatch
}
else {
[mapView.userLocation setTitle:@"I am here"];
}
return pinView;
}
Notice that animatesDrop
is also commented out since that property only exists in MKPinAnnotationView
.
If you still want your image annotations to drop, you'll have to do the animation yourself. You can search Stack Overflow for "animatesdrop mkannotationview" and you'll find several answers. Here are the first two:
- Is it possible to call animatesDrop in a MKAnnotationView rather than MKPinAnnotationView?
- How can I create a custom "pin-drop" animation using MKAnnotationView?
Swift - MKPinAnnotation image issue
You want MKAnnotationView
, not MKPinAnnotationView
. Pin annotations can't customize their image.
See this SO answer for additional details
Stuck on using MKPinAnnotationView() within Swift and MapKit
You need to implement the viewForAnnotation
delegate method and return an MKAnnotationView
(or subclass) from there.
This is just like in Objective-C -- the underlying SDK works the same way.
Remove the creation of MKPinAnnotationView
from the for
loop that adds the annotations and implement the delegate method instead.
Here is a sample implementation of the viewForAnnotation
delegate method in Swift:
func mapView(mapView: MKMapView!,
viewForAnnotation annotation: MKAnnotation!) -> MKAnnotationView! {
if annotation is MKUserLocation {
//return nil so map view draws "blue dot" for standard user location
return nil
}
let reuseId = "pin"
var pinView = mapView.dequeueReusableAnnotationViewWithIdentifier(reuseId) as? MKPinAnnotationView
if pinView == nil {
pinView = MKPinAnnotationView(annotation: annotation, reuseIdentifier: reuseId)
pinView!.canShowCallout = true
pinView!.animatesDrop = true
pinView!.pinColor = .Purple
}
else {
pinView!.annotation = annotation
}
return pinView
}
Related Topics
C# Generics Compared to C++ Templates
Reading/Writing from Named Pipes Under Mono/Linux
Non Client Painting on Aero Glass Window
Load Different CSS File Based on Browser
String List in SQLcommand Through Parameters in C#
.Net Decompiler for MAC or Linux
Asp.Net MVC Using Web API to Return a Razor View
C#: Referencing or Using .So Files in .Net Core on Linux
Duplicate Key Exception from Entity Framework
Why Does a Float Variable Stop Incrementing at 16777216 in C#
Entity Framework the Underlying Provider Failed on Open
Error While Using Executenonquery C#
Monodevelop + Naudio + Ubuntu Linux Tells Me Winmm.Dll Not Found