我正在尝试缩放到随机注释并自动打开气泡。
我将注释固定在viewDidLoad中,如下所示:
...arrays...
for (int i=0; i<22; i++){
MKPointAnnotation *annot = [[MKPointAnnotation alloc] init];
annot.title = [wineryName objectAtIndex:i];
annot.subtitle = [wineryAddress objectAtIndex:i];
annot.coordinate = CLLocationCoordinate2DMake([[lat objectAtIndex:i]doubleValue], [[lon objectAtIndex:i]doubleValue]);
[mapView setCenterCoordinate:annot.coordinate animated:YES];
[mapView addAnnotation:annot];
然后我按照以下方式设置泡泡样式:
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
if ([annotation isKindOfClass:[MKUserLocation class]])
return nil;
//dequeue an existing pin view first
static NSString* AnnotationIdentifier = @"AnnotationIdentifier";
MKPinAnnotationView* pinView = [[[MKPinAnnotationView alloc]
initWithAnnotation:annotation reuseIdentifier:AnnotationIdentifier] autorelease];
pinView.animatesDrop=YES;
pinView.canShowCallout=YES;
pinView.pinColor=MKPinAnnotationColorRed;
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
button.frame = CGRectMake(0, 0, 35, 35);
button.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter;
[button setImage:[UIImage imageNamed:@"RightArrow.png"] forState:UIControlStateNormal];
[button addTarget:self action:@selector(showDetails:) forControlEvents:UIControlEventTouchUpInside];
pinView.rightCalloutAccessoryView = button;
...arrays...
for (int i = 0; i < 22; i++) {
if ([wineryTitle[i] isEqualToString:[annotation title]]) {
UIImageView *profileIconView = [[UIImageView alloc] init];
profileIconView.frame = CGRectMake(0, 0, 40, 33);
profileIconView.image = [UIImage imageNamed:wineryImage[i]];
pinView.leftCalloutAccessoryView = profileIconView;
[profileIconView release];
break;
}
}
return pinView;
}
然后我尝试按如下方式缩放到随机位置:
- (void)zoomToUserLocation:(MKUserLocation *)userLocation
{
if (!userLocation)
return;
MKCoordinateRegion region;
//zoom to random pin when page loads
int randomNumber = rand() % 22;
switch (randomNumber) {
case 1:
region.center = CLLocationCoordinate2DMake(34.642109, -120.440292);
[self.mapView selectAnnotation:[self.mapView.annotations objectAtIndex:0] animated:TRUE];
break;
case 2:
region.center = CLLocationCoordinate2DMake(34.667408, -120.334781);
[self.mapView selectAnnotation:[self.mapView.annotations objectAtIndex:1] animated:TRUE];
break;
case 3:
...etc
}
region.span = MKCoordinateSpanMake(5.0, 5.0);
region = [self.mapView regionThatFits:region];
[self.mapView setRegion:region animated:YES];
}
所有这些工作&lt; EXCEPT:在zoomToUserLocation方法中,地图缩放到一个位置,然后显示不同位置的气泡。似乎随机运算符分别随机选择一个位置和一个气泡。有谁知道如何解决这个问题,以便气泡自动出现在随机选择的相同位置?
答案 0 :(得分:0)
zoomToUserLocation
方法中的代码假设地图视图的annotations
数组仅包含您明确添加的注释,(更重要的是)annotations
数组将包含注释与您在。中添加注释的顺序相同。
这两种假设都不安全 有关更多讨论,请参阅MKMapView annotations changing/losing order?。
您的应用显然添加了22个注释,但是:
showsUserLocation
为YES,则地图视图的annotations
数组将包含23个注释(您的22和地图自行添加的用户位置)。annotations
数组的索引N处的注释与酿酒厂数组中索引N处的注释相同。出于简单缩放到随机位置的目的,没有必要在地图的annotations
数组和您自己的数组之间建立链接。
相反,可以从annotations
数组本身随机选择的注释中检索以中心为中心的坐标。
例如:
MKCoordinateRegion region;
//make list of annotations excluding the user location
NSMutableArray *myAnnotations = [NSMutableArray arrayWithCapacity:10];
for (id<MKAnnotation> ann in self.mapView.annotations)
{
if (! ([ann isKindOfClass:[MKUserLocation class]]))
[myAnnotations addObject:ann];
}
int numOfAnnotations = myAnnotations.count;
//if no annotations to choose from, do nothing
if (numOfAnnotations == 0)
return;
int randomNumber = rand() % numOfAnnotations;
//suggest using arc4random instead of rand
//see https://stackoverflow.com/questions/160890/generating-random-numbers-in-objective-c
id<MKAnnotation> randomAnnotation = [myAnnotations objectAtIndex:randomNumber];
region.center = randomAnnotation.coordinate;
[self.mapView selectAnnotation:randomAnnotation animated:YES];
region.span = ... //rest of the code as-is
//however, calling regionThatFits is unnecessary
可以对代码进行许多其他无关的改进,但这些改进必须是单独问题的主题。以下是其中的几个......
我可以建议的一个主要改进是创建一个自定义注释类(也许称为Winery
),它将酒厂的所有数据合并为一个对象,而不是使用单独的数组作为名称,地址,纬度,经度,图像等。
这将使开发和未来的变更更容易管理。
第二个主要改进是删除viewForAnnotation
委托方法中的低效循环,该方法搜索酒厂名称以设置左侧辅助视图的图像。每次需要注释视图时都会执行此搜索循环。只需22个注释,您可能不会注意到性能问题,但这是不必要的工作。如果第一次改进完成,则可以删除搜索循环,因为所有注释的属性都已经在注释对象中。
请参阅Optimizing Code for MKMapView - Large Number of Annotations了解上述内容。