代码之家  ›  专栏  ›  技术社区  ›  Max1980

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

  •  1
  • Max1980  · 技术社区  · 10 年前

    在我的应用程序中,一切都很好,除了一件事:放大和缩小后,为了查看整个地图,一些标注打开了错误的详细视图。 我不知道我是不是漏掉了一些代码。 对iOS7使用Xcode 5.1.1。 这是我目前所得到的:

    注释.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
    

    注释.m

    #import "Annotation.h"
    
    @implementation Annotation
    @synthesize coordinate,title,subtitle;
    
    @end
    

    地图视图.h

    #import <UIKit/UIKit.h>
    #import <MapKit/MapKit.h>
    
    @interface Nameofthemap : UIViewController <MKMapViewDelegate>
    
    @property (strong, nonatomic) IBOutlet MKMapView *Nameofthemap;
    
    @end
    

    地图视图.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
    
    1 回复  |  直到 10 年前
        1
  •  0
  •   user467105 user467105    10 年前

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

    在里面 viewForAnnotation ,按钮目标仅在创建视图时设置(如果 dequeueReusableAnnotationViewWithIdentifier 回报 nil ).

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

    先前的注释可能与当前注释不同。

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

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

    1. 如果 dequeueReusableAnnotationViewWithIdentifier 返回视图(如果 pinView 不是 ),代码 必须 更新视图的 annotation 属性设置为当前批注。
    2. 无论是创建新视图还是重新使用已退出队列的视图,都必须设置按钮目标。最简单的方法是将按钮创建/设置移动到 if 就在 return .

    更新的 注释视图 将如下所示:

    - (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 委托方法。

    事实上,现在,map视图正在调用自定义方法和 Callout AccessoryControl抽头 委托方法(其中当前没有代码)。

    在委托方法中,可以通过 view.annotation .

    所以在 注释视图 ,您可以这样做:

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

    然后在 Callout AccessoryControl抽头 委托方法,可以执行以下操作:

    - (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 正在使用 地点2_经度 而不是 PLACE1_LONGITUDE