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

时间:2014-07-11 16:18:11

标签: ios mapkit mkannotation ios7.1

除了一件事,我的应用程序中的一切工作正常:放大并缩小后,要查看整个地图,一些标注会打开错误的详细视图。 我不知道我是否遗漏了一些代码。 使用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

1 个答案:

答案 0 :(得分:0)

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

viewForAnnotation中,仅在创建视图时设置按钮目标(如果dequeueReusableAnnotationViewWithIdentifier返回nil)。

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

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

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

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

  1. 如果dequeueReusableAnnotationViewWithIdentifier返回视图(如果pinView不是nil),则代码必须将视图的annotation属性更新为当前注释
  2. 必须设置按钮目标,无论是创建新视图还是重新使用出列视图。最简单的方法是在主if之后和return之前移动按钮创建/设置。
  3. 更新的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];
        }
    }
    

    然后删除myAnnClickedmyAnn2Clicked方法。

    为每个注释创建一个通用的“Info”视图控制器而不是单独的视图控制器也会好得多。

    其他一些不相关的事情:

    • 请勿在{{1​​}}行
    • 的末尾添加分号
    • 您已定义#define两次
    • PLACE2_LONGITUDE正在使用newRegion.center而不是PLACE2_LONGITUDE