标注放大iOS7后打开错误的视图

在我的应用程序中一切正常,除了一件事:放大和缩小后,看到整个地图,一些标注打开错误的detailview。 我不知道如果我错过了一些代码或其他。 使用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 

这是一个注释视图重用问题。

viewForAnnotation ,只有在创build视图时才设置button目标(如果dequeueReusableAnnotationViewWithIdentifier返回nil )。

但是,如果dequeueReusableAnnotationViewWithIdentifier返回以前使用的视图,则button目标仍然是为之前使用视图的注释设置的值。

以前的注释可能与当前的注释不一样。

因此,注释“two”可能会重新使用最初为注释“one”创build的视图,而点击已经创build的button会显示“one”而不是“two”的信息。

要解决这个问题,应该做两件事:

  1. 如果dequeueReusableAnnotationViewWithIdentifier返回一个视图(如果pinView不是nil ),则代码必须将视图的annotation属性更新为当前注释。
  2. 必须设置button目标是否正在创build新视图或正在重新使用出队视图。 最简单的方法是在return之前和之后移动button创build/设置。

更新的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; } 


顺便说一下,不是为每个注释创build单独的方法(这可能很乏味),而是使用地图视图的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]; } } 

然后删除myAnnClickedmyAnn2Clicked方法。

你也可以创build一个通用的“信息”视图控制器,而不是每个注释单独的一个。

一些其他无关的事情:

  • 不要在#define行的末尾放一个分号
  • 您已经定义了PLACE2_LONGITUDE两次
  • newRegion.center正在使用PLACE2_LONGITUDE而不是PLACE1_LONGITUDE