缩放到随机注释并在地图视图加载时显示气泡

时间:2013-06-22 23:47:02

标签: ios mapkit

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

我将注释固定在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方法中,地图缩放到一个位置,然后显示不同位置的气泡。似乎随机运算符分别随机选择一个位置和一个气泡。有谁知道如何解决这个问题,以便气泡自动出现在随机选择的相同位置?

1 个答案:

答案 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了解上述内容。