2014-07-11 3 views
1

한 가지를 제외하고 모든 것이 내 앱에서 정상적으로 작동하고 있습니다. 전체지도를 보려면 확대/축소하고 축소 한 후 일부 콜 아웃이 잘못된 detailview를 엽니 다. 일부 코드가 누락 된 것인지 알 수 없습니다. iOS7 용 Xcode 5.1.1 사용.콜 아웃이 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

그것은 주석보기 재사용 문제입니다.

viewForAnnotation에서 버튼 대상은보기를 만들 때 설정됩니다 (dequeueReusableAnnotationViewWithIdentifiernil 인 경우).

그러나 dequeueReusableAnnotationViewWithIdentifier이 이전에 사용한보기를 반환하는 경우 버튼 대상은 이전에보기를 사용하는 주석에 설정된 항목이 그대로 유지됩니다.

이전 주석은 현재 주석과 다를 수 있습니다.

주석 "two"는 주석 "one"을 위해 원래 생성 된 뷰를 재사용 할 수 있으며 이미 생성 된 버튼을 탭하면 "two"대신 "one"에 대한 정보가 표시됩니다. 이 문제를 해결하려면

는 두 가지를 수행해야합니다 : ( pinViewnil가 아닌 경우) dequeueReusableAnnotationViewWithIdentifier이 뷰를 돌려줍니다

  1. 경우 코드 현재 주석에 뷰의 annotation 속성을 업데이트해야합니다.
  2. 버튼 대상은 새보기를 만들지 또는 대기중인보기를 다시 사용할지 여부를 설정해야합니다. 이를 수행하는 가장 쉬운 방법은 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을 통해 액세스 할 수 있습니다.

- (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 위임 방법, 당신은 같은 것을 할 수 있습니다 :

그래서 viewForAnnotation에, 당신은이 작업을 수행 할 것
- (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"보기 컨트롤러를 만드는 것이 훨씬 낫습니다.

다른 어떤 관련이없는 것들 :

  • 당신은 두 번
  • newRegion.centerPLACE1_LONGITUDE
  • 대신 PLACE2_LONGITUDE을 사용 PLACE2_LONGITUDE을 정의한
  • #define 라인의 끝에 세미콜론을 넣지 마십시오
+0

Thanx Anna. 이제 모든 것이 잘 작동합니다! Map 뷰의 calloutAccessoryControlTapped 위임 메서드를 사용 했으므로 제안한대로 실제로 더 좋습니다. 좌표는 잘라 붙이기 실수였습니다. 어쨌든 그것을 지적하기위한 고맙습니다. – Max1980