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

Posted

技术标签:

【中文标题】在 iPhone 中,我如何知道在使用正向地理编码时我的所有地图注释何时加载?【英文标题】:In iPhone how do I know when all of my map's annotations have loaded while using forward geocode? 【发布时间】:2013-07-11 23:08:00 【问题描述】:

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

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

我还想指出,我正在使用正向地理编码来获取我的注释坐标。

这是我的观点确实出现了:

[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];
                 
             
];

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

【问题讨论】:

【参考方案1】:

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

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

【讨论】:

【参考方案2】:

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

【讨论】:

【参考方案3】:

在所有注解都经过地理编码并加载到地图上之后运行方法的最佳方式似乎是运行简单的计数和 if 语句检查计数与数组计数。

这是我想出的: int pointsArrayCount = contactArray.count; NSLog(@"Count : %d", pointsArrayCount); int numberOfPoints = pointsArrayCount; NSLog(@"Count Number : %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 个地理编码。因此,这仅在您在地理编码时向地图加载少量数据时才有效。如果您做的不止这些,那么您应该将所有坐标存储在某个地方,然后在地图加载时单独加载它们。

【讨论】:

以上是关于在 iPhone 中,我如何知道在使用正向地理编码时我的所有地图注释何时加载?的主要内容,如果未能解决你的问题,请参考以下文章

iPhone地理编码

使用 CLGeocoder 的正向地理编码示例

在 iPhone 上使用地理编码检查地址的有效性

单个应用程序中的正向和反向地理编码:需要方向

iOS 正向地理编码返回不稳定、稀疏的结果

使用 iPhone 的纬度和经度进行反向地理编码