1

我正在尝试缩放到随机注释并自动打开气泡。

我将注释固定在 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];

}

所有这些工作<除了:在 zoomToUserLocation 方法中,地图缩放到一个位置,然后显示另一个位置的气泡。似乎随机操作员正在分别随机选择一个位置和一个气泡。有谁知道如何解决这个问题,以便气泡自动出现在随机选择的同一位置?

4

1 回答 1

0

zoomToUserLocation方法中的代码错误地假设地图视图的annotations数组仅包含您显式添加的注释,并且(更重要的是)该annotations数组的顺序与您添加注释的顺序相同。

这两个假设都是不安全的。
有关更多讨论,请参阅MKMapView 注释更改/丢失顺序?.

您的应用显然添加了 22 个注释,但是:

  • 如果showsUserLocation是,那么地图视图的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 个注释,您可能不会注意到性能问题,但这是不必要的工作。如果完成了第一个改进,则可以消除搜索循环,因为所有注释的属性都已经在注释对象中。

有关上述的一些想法,请参阅MKMapView 的优化代码 - 大量注释

于 2013-06-23T02:53:13.503 回答