除了一件事,我的应用程序中的一切工作正常:放大并缩小后,要查看整个地图,一些标注会打开错误的详细视图。 我不知道我是否遗漏了一些代码。 使用Xcode 5.1.1 for iOS7。 这就是我现在所拥有的:
Annotation.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;
@end
Annotation.m
#import "Annotation.h"
@implementation Annotation
@synthesize coordinate,title,subtitle;
@end
MapView.h
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
@interface Nameofthemap : UIViewController <MKMapViewDelegate>
@property (strong, nonatomic) IBOutlet MKMapView *Nameofthemap;
@end
MapView.m
#import "MapView.h"
#import "Annotation.h"
#import "InfoViewController.h"
#import "InfoTwoViewController.h"
@interface MapView ()
@property (nonatomic, strong) IBOutlet InfoViewController *InfoViewController;
@property (nonatomic, strong) IBOutlet InfoTwoViewController *InfoTwoViewController;
@end
#define PLACE1_LATITUDE 43.777130;
#define PLACE2_LONGITUDE 10.790018;
#define PLACE2_LATITUDE 43.81471237;
#define PLACE2_LONGITUDE 10.67472765;
@implementation MapView
- (IBAction)changeMapType:(id)sender {
if (_MapView.mapType == MKMapTypeHybrid)
_MapView.mapType = MKMapTypeStandard;
else
_MapView.mapType = MKMapTypeHybrid;
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self gotoLocation];
_MapView.showsUserLocation = YES;
}
- (void)gotoLocation
{
MKCoordinateRegion newRegion;
newRegion.center.latitude = PLACE1_LATITUDE;
newRegion.center.longitude = PLACE2_LONGITUDE;
newRegion.span.latitudeDelta = 0.25f;
newRegion.span.longitudeDelta = 0.25f;
[self.MapView setRegion:newRegion animated:YES];
NSMutableArray * locations = [[NSMutableArray alloc] init];
CLLocationCoordinate2D location;
Annotation *myAnn;
Annotation *myAnn2;
//Place1 annotation
myAnn = [[Annotation alloc] init];
location.latitude = PLACE1_LATITUDE;
location.longitude = PLACE1_LONGITUDE;
myAnn.coordinate = location;
myAnn.title = @"Name of the place";
myAnn.subtitle = @"Details";
[locations addObject:myAnn];
//Place2 annotation
myAnn2 = [[Annotation alloc] init];
location.latitude = PLACE2_LATITUDE;
location.longitude = PLACE2_LONGITUDE;
myAnn2.coordinate = location;
myAnn2.title = @"Name of place two";
myAnn2.subtitle = @"Details";
[locations addObject:myAnn2];
[self->_MapView addAnnotations:locations];
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control{
}
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)myAnn {
if ([myAnn isKindOfClass:[MKUserLocation class]])
{
((MKUserLocation *)myAnn).title = @"Your position";
return nil;
}
MKPinAnnotationView *pinView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:@"pinView"];
if (!pinView) {
pinView = [[MKPinAnnotationView alloc] initWithAnnotation:myAnn reuseIdentifier:@"pinView"];
pinView.pinColor = MKPinAnnotationColorRed;
pinView.canShowCallout = YES;
UIButton *rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
if ([[myAnn title] isEqualToString:@"Name of the place"]){
[rightButton addTarget:self action:@selector(myAnnClicked:)forControlEvents:UIControlEventTouchUpInside];
}
if ([[myAnn title] isEqualToString:@"Name of place two"]){
[rightButton addTarget:self action:@selector(myAnn2Clicked:)forControlEvents:UIControlEventTouchUpInside];
}
pinView.rightCalloutAccessoryView = rightButton;
}
return pinView;
}
-(IBAction)myAnnClicked:(id)sender
{
InfoViewController *info = [[InfoViewController alloc]init];
[self.navigationController pushViewController:info animated:YES];
}
-(IBAction)myAnn2Clicked:(id)sender
{
InfoTwoController *info2 = [[InfoTwoController alloc]init];
[self.navigationController pushViewController:info2 animated:YES];
}
@end
答案 0 :(得分:0)
这是一个注释视图重用问题。
在viewForAnnotation
中,仅在创建视图时设置按钮目标(如果dequeueReusableAnnotationViewWithIdentifier
返回nil
)。
但是如果dequeueReusableAnnotationViewWithIdentifier
返回先前使用过的视图,那么按钮目标仍然是为之前使用该视图的注释设置的内容。
之前的注释可能与当前注释不同。
因此,注释“two”可以重复使用最初为注释“one”创建的视图,并且点击已经创建的按钮会显示“one”而不是“two”的信息。
要解决这个问题,应该做两件事:
dequeueReusableAnnotationViewWithIdentifier
返回视图(如果pinView
不是nil
),则代码必须将视图的annotation
属性更新为当前注释if
之后和return
之前移动按钮创建/设置。更新的viewForAnnotation
将如下所示:
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)myAnn {
if ([myAnn isKindOfClass:[MKUserLocation class]])
{
((MKUserLocation *)myAnn).title = @"Your position";
return nil;
}
MKPinAnnotationView *pinView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:@"pinView"];
if (!pinView) {
pinView = [[MKPinAnnotationView alloc] initWithAnnotation:myAnn reuseIdentifier:@"pinView"];
pinView.pinColor = MKPinAnnotationColorRed;
pinView.canShowCallout = YES;
}
else
{
//1. Re-using a view, update which annotation it's being used for now
pinView.annotation = myAnn;
}
//2. Now pinView is either a new view or re-used view.
//Set its button target based on current annotation...
UIButton *rightButton = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
if ([[myAnn title] isEqualToString:@"Name of the place"]){
[rightButton addTarget:self action:@selector(myAnnClicked:)forControlEvents:UIControlEventTouchUpInside];
}
if ([[myAnn title] isEqualToString:@"Name of place two"]){
[rightButton addTarget:self action:@selector(myAnn2Clicked:)forControlEvents:UIControlEventTouchUpInside];
}
pinView.rightCalloutAccessoryView = rightButton;
return pinView;
}
顺便说一下,不是为每个注释创建单独的方法(这可能会变得单调乏味),而是使用地图视图的calloutAccessoryControlTapped
委托方法。
事实上,现在,地图视图正在调用您的自定义方法和calloutAccessoryControlTapped
委托方法(当前没有代码)。
在委托方法中,可以通过view.annotation
访问已点按的注释。
所以在viewForAnnotation
中,您只需执行此操作:
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)myAnn {
if ([myAnn isKindOfClass:[MKUserLocation class]])
{
((MKUserLocation *)myAnn).title = @"Your position";
return nil;
}
MKPinAnnotationView *pinView = (MKPinAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:@"pinView"];
if (!pinView) {
pinView = [[MKPinAnnotationView alloc] initWithAnnotation:myAnn reuseIdentifier:@"pinView"];
pinView.pinColor = MKPinAnnotationColorRed;
pinView.canShowCallout = YES;
pinView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
}
else
{
pinView.annotation = myAnn;
}
return pinView;
}
然后在calloutAccessoryControlTapped
委托方法中,您可以执行以下操作:
- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view calloutAccessoryControlTapped:(UIControl *)control{
if ([view.annotation isKindOfClass:[Annotation class]])
{
Annotation *myAnn = (Annotation *)view.annotation;
id vcToPush = nil;
if ([[myAnn title] isEqualToString:@"Name of the place"]) {
vcToPush = [[InfoViewController alloc]init];
}
else if ([[myAnn title] isEqualToString:@"Name of place two"]) {
vcToPush = [[InfoTwoController alloc]init];
}
[self.navigationController pushViewController:vcToPush animated:YES];
}
}
然后删除myAnnClicked
和myAnn2Clicked
方法。
为每个注释创建一个通用的“Info”视图控制器而不是单独的视图控制器也会好得多。
其他一些不相关的事情:
#define
两次PLACE2_LONGITUDE
正在使用newRegion.center
而不是PLACE2_LONGITUDE