在iPhone中,如何在使用前向地理编码时知道我的所有地图注释都已加载?

时间:2013-07-11 23:08:01

标签: ios maps mkannotation clgeocoder completionhandler

在我的应用程序中,我有一个表格视图,可以在地图视图上切换注释。我可以通过标签栏控制器在表格视图和地图视图之间来回切换。我的地图将在视图上重新加载注释(来自表视图中的选定项目)。我需要知道这些注释何时完成加载,以便我可以运行我的方法,缩放到由注释簇确定的生成区域。

问题是当我在视图中的addAnnotations方法出现后直接运行zoom方法时,它会在我的注释获得正确坐标之前开始缩放过程。因此导致缩放不正确,并且我的注释移动到正确的位置。

我还要注意,我正在使用前向地理编码来获取我的注释坐标。

以下是我的观点:

[super viewDidAppear:animated];

[businessMap removeAnnotations:businessPoints];
[businessPoints removeAllObjects];

UINavigationController *navVC = (UINavigationController *) [self.tabBarController.viewControllers objectAtIndex:0];

FirstViewController *VC = [navVC.viewControllers objectAtIndex:0];

for (businessInfo *business_info in VC.selectedBusinessesArray) {



    businessInfoAnnotation *businessAnnotation = [[businessInfoAnnotation alloc] init];

    businessAnnotation.businessInfoClass = business_info;

    CLGeocoder *geocoder = [[CLGeocoder alloc] init];

    [geocoder geocodeAddressString:business_info.location
                 completionHandler:^(NSArray* geocoded, NSError* error){
                     if (geocoded && geocoded.count > 0) {
                         CLPlacemark *placemark = [geocoded objectAtIndex:0];
                         CLLocation *location = placemark.location;
                         CLLocationCoordinate2D business_cords = location.coordinate;
                         businessAnnotation.coordinate = business_cords;
                     }
                 }];

    businessAnnotation.title = business_info.name;

    [businessPoints addObject:businessAnnotation];

}

[businessMap addAnnotations:businessPoints];

[businessMap setZoomEnabled:YES];

[self zoomToFitMapAnnotations:businessMap withArray:businessPoints];

这是我的缩放方法:

-(void)zoomToFitMapAnnotations:(MKMapView*)mapViews withArray:(NSArray*)anAnnotationArray
{
    if([mapViews.annotations count] == 0) return;

    CLLocationCoordinate2D topLeftCoord;
    topLeftCoord.latitude = -90;
    topLeftCoord.longitude = 180;
    NSLog(@"zooming");

    CLLocationCoordinate2D bottomRightCoord;
    bottomRightCoord.latitude = 90;
    bottomRightCoord.longitude = -180;



    for(MKPointAnnotation* annotation in anAnnotationArray)
    {
        topLeftCoord.longitude = fmin(topLeftCoord.longitude, annotation.coordinate.longitude);
        topLeftCoord.latitude = fmax(topLeftCoord.latitude, annotation.coordinate.latitude);

        bottomRightCoord.longitude = fmax(bottomRightCoord.longitude, annotation.coordinate.longitude);
        bottomRightCoord.latitude = fmin(bottomRightCoord.latitude, annotation.coordinate.latitude);
    }

    MKCoordinateRegion region;
    region.center.latitude = topLeftCoord.latitude - (topLeftCoord.latitude - bottomRightCoord.latitude) * 0.5;
    region.center.longitude = topLeftCoord.longitude + (bottomRightCoord.longitude - topLeftCoord.longitude) * 0.5;
    region.span.latitudeDelta = fabs(topLeftCoord.latitude - bottomRightCoord.latitude) * 1.1;
    region.span.longitudeDelta = fabs(bottomRightCoord.longitude - topLeftCoord.longitude) * 1.1;

    region = [mapViews regionThatFits:region];
    [businessMap setRegion:region animated:YES];
}

感谢您的帮助。对不起,如果这是草率的,这是我的第一篇文章。

修改
根据nevan king的回答,这是我编辑的地理编码方法。

[geocoder geocodeAddressString:business_info.location
             completionHandler:^(NSArray* geocoded, NSError* error){
                 if (geocoded && geocoded.count > 0) {
                     CLPlacemark *placemark = [geocoded objectAtIndex:0];
                     CLLocation *location = placemark.location;
                     CLLocationCoordinate2D business_cords = location.coordinate;
                     businessAnnotation.coordinate = business_cords;

                     businessAnnotation.title = business_info.name;

                     [businessPoints addObject:businessAnnotation];

                     [businessMap addAnnotations:businessPoints];

                     [self zoomToFitMapAnnotations:businessMap withArray:businessPoints];
                 }
             }
];

同样不是我尝试使用注释数组的计数来确定最后一个注释的地理编码completionHandler,以仅更改该特定区域上的区域。但这对我的地区产生了不一致的结果。这是在视图中始终保持所有注释的唯一方法。

3 个答案:

答案 0 :(得分:2)

MKMapViewDelegate有一个mapView:didAddAnnotationViews:方法,在一组注释视图放置在地图上后调用。请注意,它与注释不同(根据缩放,某些注释可能不可见)。

修改:我刚刚注意到您首先对地点进行地理编码。在这种情况下,您必须在地理编码完成处理程序中将注释添加到地图中。在主线程上执行。在您的代码中,当您调用addAnnotations:时,完成块尚未完成。

答案 1 :(得分:0)

您可以使用调度组,但我相信您必须手动使用dispatch_group_enter和dispatch_group_leave,而不是dispatch_group_async。这样,您可以在每次调用geocodeAddressString之前输入组,并在完成块完成后离开组。完成所有完成块后,dispatch_notify将调用您的代码进行调整大小。

答案 2 :(得分:0)

在地图上对所有注释进行地理编码并加载后运行方法的最佳方法是运行一个简单的计数和一个if语句,用数组计数检查计数。

这是我提出的:     int pointsArrayCount = contactArray.count;     NSLog(@“Count:%d”,pointsArrayCount);     int numberOfPoints = pointsArrayCount;     NSLog(@“计数:%d”,numberOfPoints);     i = 0;

for (contactInfo *contact_info in contactArray) {

    contatcInfoAnnotation *annotation = [[contatcInfoAnnotation alloc] init];

    annotation.contactInfoClass = contact_info;

    CLGeocoder *geocoder = [[CLGeocoder alloc] init];

    [geocoder geocodeAddressString:contact_info.address
                 completionHandler:^(NSArray* geocoded, NSError* error){
                     if (geocoded && geocoded.count > 0) {
                         CLPlacemark *placemark = [geocoded objectAtIndex:0];
                         CLLocation *location = placemark.location;
                         CLLocationCoordinate2D contact_cords = location.coordinate;
                         annotation.coordinate = contact_cords;

                         annotation.title = contact_info.name;

                         [mapPoints addObject:annotation];

                         [mapView addAnnotations:mapPoints];

                         i++;

                         NSLog(@"Count Number of Geocoded: %d", i);

                         if(i == numberOfPoints) {
                             [self zoomToFitMapAnnotations:mapView withArray:mapPoints];
                         }
                     }
                 }//end completionHandler
     ];

但是,完成处理程序最多只能处理40个地理编码。因此,只有在地理编码时向地图加载少量数据时,这才有效。如果你做的不止于此,那么你应该将所有坐标存储在某处,然后在加载地图时单独加载它们。