在我的应用中,有一个mapView,用户可以通过按屏幕添加注释。当注释被放到mapView上时,它们会被添加到单例中的可变数组中。注释视图有一个callout按钮,当按下它时,它会将详细视图(称为PinViewController)推入堆栈。我的问题是,当按下callout按钮时,我想将该注释对象的索引传递给详细视图控制器,以便我可以从该对象获取地址和日期。但每当我按下callout按钮时,无论它是哪个注释,它总是传递数组中第一个对象的索引。我不明白我做错了什么,有人可以帮帮我吗?这是一些代码:
- (void)mapView:(MKMapView *)mapView
annotationView:(MKAnnotationView *)view
calloutAccessoryControlTapped:(UIControl *)control {
PinViewController *pvc = [[PinViewController alloc]init];
[[self navigationController]pushViewController:pvc animated:YES];
NSUInteger pinIndex = [[Data singleton].annotations indexOfObject:view.annotation];
[pvc setIdentifier:pinIndex];
}
这是来自详细视图控制器:
- (void)viewDidLoad {
[super viewDidLoad];
[self.labelView setFrame:CGRectMake(10, 260, 300, 230)];
[PinViewController roundView:self.labelView onCorner:UIRectCornerAllCorners radius:15];
[[self view]addSubview:self.labelView];
self.annotation = [[Data singleton].annotations objectAtIndex:self.identifier];
self.addressLabel.text = self.annotation.address;
self.dateLabel.text = self.annotation.subtitle;
}
以下是将注释添加到数组的位置:
- (void)press:(UILongPressGestureRecognizer *)recognizer {
CGPoint touchPoint = [recognizer locationInView:self.worldView];
CLLocationCoordinate2D touchMapCoordinate = [self.worldView convertPoint:touchPoint toCoordinateFromView:self.worldView];
self.geocoder = [[CLGeocoder alloc]init];
CLLocation *location = [[CLLocation alloc]initWithCoordinate:touchMapCoordinate
altitude:CLLocationDistanceMax
horizontalAccuracy:kCLLocationAccuracyBest
verticalAccuracy:kCLLocationAccuracyBest
timestamp:[NSDate date]];
[self.geocoder reverseGeocodeLocation:location
completionHandler:^(NSArray *placemarks, NSError *error) {
//NSLog(@"reverseGeocoder:completionHandler: called");
if (error) {
NSLog(@"Geocoder failed with error: %@", error);
} else {
CLPlacemark *place = [placemarks objectAtIndex:0];
self.geocodedAddress = [NSString stringWithFormat:@"%@ %@, %@ %@", [place subThoroughfare], [place thoroughfare], [place locality], [place administrativeArea]];
if (UIGestureRecognizerStateBegan == [recognizer state]) {
self.addressPin = [[MapPoint alloc]initWithAddress:self.geocodedAddress
coordinate:touchMapCoordinate
title:self.geocodedAddress];
[[Data singleton].annotations addObject:self.addressPin];
[self.worldView addAnnotation:self.addressPin];
NSLog(@"The number of pins in the annotation array is: %u",[Data singleton].annotations.count);
}
}
}];
}
基本上,传递给PinViewController的索引总是0,无论它是哪个注释。我不明白为什么这段代码不起作用。
答案 0 :(得分:3)
NSArray indexOfObject方法在每个数组成员上调用isEqual以确定它们是否相同。你确定你的对象只有在它们真正相等的情况下才会返回YES吗?我怀疑你的对象返回YES,即使它们是不等的
从索引0开始,数组的每个元素都发送一个isEqual: 消息,直到找到匹配或到达数组的末尾。 此方法将anObject参数传递给每个isEqual:消息。 如果isEqual:对象被认为是相等的(在NSObject中声明 protocol)返回YES。
像NSNumber这样的基础类已经为你实现了isEqual
,因此你可以在数组indexOfObjects
方法中立即使用它
NSMutableArray* arr = [[NSMutableArray alloc] init];
[arr addObject:[NSNumber numberWithInt:3]];
[arr addObject:[NSNumber numberWithInt:2]];
[arr indexOfObject:[NSNumber numberWithInt:2]]; // gives 1
但是,当您实现自定义类(例如MapView
)时,Objective C不知道如何比较您的对象,因此您必须自己实现isEqual
比较器
假设MapView
有一个名为cow
的整数属性,您可以从中确定相等性(例如:如果两个MapView
具有相同的cow
值,那么它们是相等的) ,你会写这样的东西:
@interface MapView : NSObject {
}
@property (nonatomic, assign) int cow;
- (BOOL)isEqual:(id)object
@implementation MapView
@synthesize cow
- (BOOL) isEqual:(id)object
{
MapView* otherMapview = (MapView*) object;
return cow == otherMapview.cow;
}