【问题标题】:custom annotation apple mapkit自定义注释苹果mapkit
【发布时间】:2013-12-08 03:57:15
【问题描述】:

我正在尝试分配两个自定义注释,一个名为“arsenal.png”,一个名为“chelsea.png”

使用苹果 mapkit 框架,xcode 7。

需要代码帮助来实现自定义标记。

这是我的实现文件:

// 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

新增内容于 2013 年 12 月 11 日东部时间 18:31 发布

更新了 Annotations.h 文件

#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

更新了 Annotations.m 文件

#import "Annotation.h"

@implementation Annotation
@synthesize coordinate, title, subtitle, imageName;

@end

更新 TrucksViewController.h

#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>

@interface TrucksViewController : UIViewController {

}
@property (weak, nonatomic) IBOutlet MKMapView *myMapView;

@end

更新 TrucksViewController.m

(代码片段)

//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

这是我更新的 TrucksViewController.m 文件: 2013 年 12 月 11 日东部时间 20:07

// 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

【问题讨论】:

    标签: ios mapkit mkannotation apple-maps


    【解决方案1】:

    您确实需要实现 viewForAnnotation 委托方法来为您的注释显示图像,而不是标准的红色图钉。

    在该委托方法中,您需要创建并返回一个 MKAnnotationView 并将其 image 属性设置为您想要用于注释的图像。

    您将获得对地图视图请求视图的注释的引用,并使用注释的属性,相应地设置图像。

    可以将其基于注释的 title 值,但我建议改用以下方法:

    1. NSString 类型的imageName 属性添加到您的Annotation 类。在调用 addAnnotation 之前,将此属性设置为要用于注释的图像名称。例如:

      myAnn.title = @"Arsenal FC";
      myAnn.subtitle = @"The Gunners";
      myAnn.imageName = @"arsenal";
      [locations addObject:myAnn];
      
    2. viewForAnnotation委托方法中,检查注解是否为Annotation类型,然后使用其imageName属性设置注解视图的image属性:

      -(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;
      }
      

    另外,不要忘记设置地图视图的delegate 属性,否则委托方法将不会被调用。在 Interface Builder 中,将 delegate 出口连接到视图控制器。

    【讨论】:

    • 我在 TrucksViewController.m 中合并了上面的第 1 步,并更新了 Annotation.m 和 .h 以包含对 imageName 的引用。不确定如何实施第 2 步。
    • 对于第 2 步,将答案中给出的 viewForAnnotation 方法添加到 TrucksViewController.m 文件中。确保地图视图的委托属性已设置(或插座已连接)。当然还要确保图像文件 arsenal.png、chelsea.png 等包含在您的项目中。
    • 我在上面的原始帖子中包含了修改后的 TrucksViewController.m。 TrucksViewController.h 有一个出口,图像在项目中。我没有显示任何错误(是的!),但在 Simulator/Run 中显示了点,但带有默认的红色引脚(不是自定义图像)。
    • 在 Interface Builder 中,右键单击地图视图。将委托出口连接到视图控制器。或者,在 viewDidLoad 中,在“super viewDidLoad”行之后添加这一行:self.myMapView.delegate = self;
    • 成功运行(!)。没有错误,但有这个(黄色)警报/警告:Assigning to 'id&lt;MKMapViewDelegate&gt;' from incompatible type 'TrucksViewController *const __strong'
    【解决方案2】:

    您可以使用 viewForAnnotation 委托方法来创建自定义注释。

    - (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id)annotation
    

    请参阅以下教程

    http://www.codigator.com/tutorials/advanced-mapkit-tutorial-for-ios-custom-callout/

    http://ios-funda.blogspot.in/2012/08/custom-annotations-example.html

    编辑

    您需要在viewDidLoad

    中设置委托
    self.myMapView.delegate = self
    

    现在在 .h

    @interface TrucksViewController : UIViewController<MKMapViewDelegate>
    

    然后实现委托方法

    - (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;
    
    }
    

    CustomAnnotation.m中添加以下方法

    -(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];
    
    }
    

    【讨论】:

    • 我很抱歉。我花了几天时间浏览教程、视频、博客等(头部游泳)。不知道如何实现上面建议的代码。我在哪里插入上面的代码,以及如何将不同的(不同的).png 与每个位置相关联?谢谢!
    • 为什么要用drawRect来显示图片?为什么不直接设置注释视图的image 属性?您实际上并不需要自定义注释视图类来显示注释图像。
    • @Anna 您可以简单地使用注释视图的图像属性。但是如果需要复杂的自定义或者需要添加任何额外的功能,那么这个自定义注解视图类会更有帮助
    • 尽管您的情况可能需要进行此类自定义,但我认为它们不必要地使 OP 问题的简单性复杂化和混淆。
    • @Anna 是的。但我认为这种做法总是好的
    猜你喜欢
    • 1970-01-01
    • 2013-04-06
    • 2020-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多