问题
I am trying to assign two custom annotations, one called "arsenal.png" and one called "chelsea.png"
Using apple mapkit framework, xcode 7.
Need assistance with code to achieve the customized markers.
here is my implementation file:
// TrucksViewController.m
#import "TrucksViewController.h"
#import "Annotation.h"
@interface TrucksViewController ()
@end
//Wimbledon Coordinates
#define WIMB_LATITUDE 51.434783;
#define WIMB_LONGITUDE -0.213428;
//Stadium Coordinates
#define ARSENAL_LATITUDE 51.556899;
#define ARSENAL_LONGITUDE -0.106483;
#define CHELSEA_LATITUDE 51.481314;
#define CHELSEA_LONGITUDE -0.190129;
//Span
#define THE_SPAN 0.20f;
@implementation TrucksViewController
@synthesize myMapView;
#pragma mark -
#pragma mark Initialisation
- (id)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
self.title = @"Trucks";
[[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationNone];
}
return self;
}
#pragma mark -
#pragma mark UIViewController Delegates
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
- (void)viewDidUnload {
[super viewDidUnload];
}
-(void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
// Update support iOS 7
if ([self respondsToSelector:@selector(edgesForExtendedLayout)]) {
self.edgesForExtendedLayout = UIRectEdgeNone;
self.navigationController.navigationBar.translucent = NO;
}
}
-(void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
// Revert to default settings
if ([self respondsToSelector:@selector(edgesForExtendedLayout)]) {
self.edgesForExtendedLayout = UIRectEdgeAll;
}
}
- (void)viewDidLoad
{
[super viewDidLoad];
//Create Region
MKCoordinateRegion myRegion;
//Center
CLLocationCoordinate2D center;
center.latitude = ARSENAL_LATITUDE;
center.longitude = ARSENAL_LONGITUDE;
//Span
MKCoordinateSpan span;
span.latitudeDelta = THE_SPAN;
span.longitudeDelta = THE_SPAN;
//Region
myRegion.center = center;
myRegion.span = span;
//Set our mapview
[myMapView setRegion:myRegion animated:YES];
//Annotation
NSMutableArray * locations = [[NSMutableArray alloc] init];
CLLocationCoordinate2D location;
Annotation * myAnn;
//Arsenal annotation
myAnn = [[Annotation alloc] init];
location.latitude = ARSENAL_LATITUDE;
location.longitude = ARSENAL_LONGITUDE;
myAnn.coordinate = location;
myAnn.title = @"Arsenal FC";
myAnn.subtitle = @"The Gunners";
[locations addObject:myAnn];
//Chelsea annotation
myAnn = [[Annotation alloc] init];
location.latitude = CHELSEA_LATITUDE;
location.longitude = CHELSEA_LONGITUDE;
myAnn.coordinate = location;
myAnn.title = @"Chelsea FC";
myAnn.subtitle = @"The Blue Lions";
[locations addObject:myAnn];
[self.myMapView addAnnotations:locations];
}
@end
Additions posted 12/11/2013 18:31 hours Eastern
Updated Annotations.h file
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
@interface Annotation : NSObject <MKAnnotation>
@property(nonatomic, assign) CLLocationCoordinate2D coordinate;
@property(nonatomic, copy) NSString * title;
@property(nonatomic, copy) NSString * subtitle;
@property(nonatomic, copy) NSString * imageName;
@end
Updated Annotations.m file
#import "Annotation.h"
@implementation Annotation
@synthesize coordinate, title, subtitle, imageName;
@end
Updated TrucksViewController.h
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
@interface TrucksViewController : UIViewController {
}
@property (weak, nonatomic) IBOutlet MKMapView *myMapView;
@end
Updated TrucksViewController.m
(snip of code)
//Arsenal annotation
myAnn = [[Annotation alloc] init];
location.latitude = ARSENAL_LATITUDE;
location.longitude = ARSENAL_LONGITUDE;
myAnn.coordinate = location;
myAnn.title = @"Arsenal FC";
myAnn.subtitle = @"The Gunners";
myAnn.imageName = @"arsenal";
[locations addObject:myAnn];
//Chelsea annotation
myAnn = [[Annotation alloc] init];
location.latitude = CHELSEA_LATITUDE;
location.longitude = CHELSEA_LONGITUDE;
myAnn.coordinate = location;
myAnn.title = @"Chelsea FC";
myAnn.subtitle = @"The Blue Lions";
myAnn.imageName = @"chelsea";
[locations addObject:myAnn];
[self.myMapView addAnnotations:locations];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
Here is my updated TrucksViewController.m file: 12/11/2013 at 20:07 Eastern
// TrucksViewController.m
#import "TrucksViewController.h"
#import "Annotation.h"
@interface TrucksViewController ()
@end
//Wimbledon Coordinates
#define WIMB_LATITUDE 51.434783;
#define WIMB_LONGITUDE -0.213428;
//Stadium Coordinates
#define ARSENAL_LATITUDE 51.556899;
#define ARSENAL_LONGITUDE -0.106483;
#define CHELSEA_LATITUDE 51.481314;
#define CHELSEA_LONGITUDE -0.190129;
//Span
#define THE_SPAN 0.20f;
@implementation TrucksViewController
@synthesize myMapView;
//insert code per Anna
-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation: (id<MKAnnotation>)annotation
{
if ([annotation isKindOfClass:[Annotation class]])
{
static NSString *reuseId = @"ann";
MKAnnotationView *av = [mapView dequeueReusableAnnotationViewWithIdentifier:reuseId];
if (av == nil)
{
av = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:reuseId];
}
else
{
av.annotation = annotation;
}
Annotation *ann = (Annotation *)annotation;
av.image = [UIImage imageNamed:ann.imageName];
return av;
}
//return nil (default view) if annotation is not our custom type
return nil;
}
//end new code per Anna
#pragma mark -
#pragma mark Initialisation
- (id)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self) {
// Set the title for this view controller
// Note: In future we will copy over the title from any created UINavigationBar objects
self.title = @"Trucks";
[[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationNone];
}
return self;
}
#pragma mark -
#pragma mark UIViewController Delegates
- (void)viewDidUnload {
[super viewDidUnload];
}
-(void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
// Update support iOS 7
if ([self respondsToSelector:@selector(edgesForExtendedLayout)]) {
self.edgesForExtendedLayout = UIRectEdgeNone;
self.navigationController.navigationBar.translucent = NO;
}
}
-(void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
// Revert to default settings
if ([self respondsToSelector:@selector(edgesForExtendedLayout)]) {
self.edgesForExtendedLayout = UIRectEdgeAll;
}
}
- (void)viewDidLoad
{
[super viewDidLoad];
//Create Region
MKCoordinateRegion myRegion;
//Center
CLLocationCoordinate2D center;
center.latitude = ARSENAL_LATITUDE;
center.longitude = ARSENAL_LONGITUDE;
//Span
MKCoordinateSpan span;
span.latitudeDelta = THE_SPAN;
span.longitudeDelta = THE_SPAN;
//Region
myRegion.center = center;
myRegion.span = span;
//Set our mapview
[myMapView setRegion:myRegion animated:YES];
//Annotation
NSMutableArray * locations = [[NSMutableArray alloc] init];
CLLocationCoordinate2D location;
Annotation * myAnn;
//Arsenal annotation
myAnn = [[Annotation alloc] init];
location.latitude = ARSENAL_LATITUDE;
location.longitude = ARSENAL_LONGITUDE;
myAnn.coordinate = location;
myAnn.title = @"Arsenal FC";
myAnn.subtitle = @"The Gunners";
myAnn.imageName = @"arsenal.png";
[locations addObject:myAnn];
//Chelsea annotation
myAnn = [[Annotation alloc] init];
location.latitude = CHELSEA_LATITUDE;
location.longitude = CHELSEA_LONGITUDE;
myAnn.coordinate = location;
myAnn.title = @"Chelsea FC";
myAnn.subtitle = @"The Blue Lions";
myAnn.imageName = @"chelsea.png";
[locations addObject:myAnn];
[self.myMapView addAnnotations:locations];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
回答1:
You do need to implement the viewForAnnotation
delegate method to show images for your annotations instead of the standard red pin.
In that delegate method, you need to create and return an MKAnnotationView
with its image
property set to the image you want for the annotation.
You will get a reference to the annotation the map view is asking for a view for and using the annotation's properties, you set the image accordingly.
You could base it on the annotation's title
value but I'd suggest the following approach instead:
Add a
imageName
property of typeNSString
to yourAnnotation
class. Set this property to the image name to use for the annotation before you calladdAnnotation
on it. For example:myAnn.title = @"Arsenal FC"; myAnn.subtitle = @"The Gunners"; myAnn.imageName = @"arsenal"; [locations addObject:myAnn];
In the
viewForAnnotation
delegate method, check if the annotation is of typeAnnotation
and then use itsimageName
property to set the annotation view'simage
property:-(MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation { if ([annotation isKindOfClass:[Annotation class]]) { static NSString *reuseId = @"ann"; MKAnnotationView *av = [mapView dequeueReusableAnnotationViewWithIdentifier:reuseId]; if (av == nil) { av = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:reuseId]; } else { av.annotation = annotation; } Annotation *ann = (Annotation *)annotation; av.image = [UIImage imageNamed:ann.imageName]; return av; } //return nil (default view) if annotation is not our custom type return nil; }
Also, don't forget to set the map view's delegate
property otherwise the delegate method won't get called. In Interface Builder, connect the delegate
outlet to the view controller.
回答2:
You can use viewForAnnotation delegate method for creating custom annotation.
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id)annotation
See the below tutorials
http://www.codigator.com/tutorials/advanced-mapkit-tutorial-for-ios-custom-callout/
http://ios-funda.blogspot.in/2012/08/custom-annotations-example.html
EDIT
You need to set the delegate in viewDidLoad
self.myMapView.delegate = self
Now in .h
@interface TrucksViewController : UIViewController<MKMapViewDelegate>
Then implement the delegate method
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation {
if ([annotation isKindOfClass:[MKUserLocation class]]) {
return nil;
}
static NSString *defaultPinId = @"Pin";
CustomAnnotation *pinView = (CustomAnnotation *)[mapView dequeueReusableAnnotationViewWithIdentifier:defaultPinId];
if (pinView == nil) {
pinView = [[CustomAnnotation alloc]initWithAnnotation:annotation reuseIdentifier:defaultPinId];
//pinView.pinColor = MKPinAnnotationColorRed;
//pinView.animatesDrop = YES;
pinView.canShowCallout = YES;
//NSLog(@"%f",[annotation coordinate].latitude);
}
else {
pinView.annotation = annotation;
}
UIButton *btn = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
btn.frame = CGRectMake(275, 27, 30, 30);
//Adding a navigation inside a callout view
btn.tag = [sid intValue];
//NSLog(@"%i",btn.tag);
[btn addTarget:self action:@selector(YOUR_SELECTOR) forControlEvents:UIControlEventTouchUpInside];
pinView.rightCalloutAccessoryView = btn;
return pinView;
}
in CustomAnnotation.m add the below methods
-(id)initWithAnnotation:(id<MKAnnotation>)annotation reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithAnnotation:annotation reuseIdentifier:reuseIdentifier];
if (self != nil) {
CGRect frame = self.frame;
frame.size = CGSizeMake(46.0, 49.0);
self.frame = frame;
self.backgroundColor = [UIColor clearColor];
self.centerOffset = CGPointMake(-5, -5);
}
return self;
}
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
// Drawing code
[[UIImage imageNamed:@"locatorico"] drawInRect:rect];
}
来源:https://stackoverflow.com/questions/20449716/custom-annotation-apple-mapkit