【问题标题】:How to add a delay when using forward-geocoding to get Latitude and Longitude for many addresses in iOS?使用前向地理编码获取iOS中许多地址的纬度和经度时如何添加延迟?
【发布时间】:2013-01-28 06:48:57
【问题描述】:

我的核心数据中有一些地址,我需要获取它们的纬度和经度。地址的数量约为 150 到 200 个。我在线程 iPhone iOS5 CLGeocoder how to geocode a large (200) set of addresses? 中读到 iOS 将您限制为每分钟 50 个地理编码。我需要知道如何在那一分钟内触发 50 个地理编码,然后再触发 50 个,依此类推。执行代码我得到以下错误:

Geocode 失败并出现错误:Error Domain=kCLErrorDomain Code=2 “操作无法完成。(kCLErrorDomain 错误 2.)”

用户 nob1984 在我提到的线程中提出了一个可能的解决方案:

如果您需要一次对所有内容进行地理编码,则需要将地理编码与每个块之间的延迟链接在一起,并在完成之前显示某种忙碌指示符。这可能需要一些时间来处理大量的地理编码。

但我不知道如何使这些延迟正常工作。欢迎任何帮助和建议!谢谢

代码如下:

...
NSArray *arrayOfRoutePoints = fetchedObjects;
[self geolocateGroup:arrayOfRoutePoints];
...

- (void)geolocateGroup:(NSArray *)array {
for (RoutePoint *rp in array) {
    if ([rp.addressLatitude intValue] == 0) {
        dispatch_group_t group = dispatch_group_create();
        dispatch_group_enter(group);

        [self geolocateRoutePoint:rp];

        dispatch_group_leave(group);

        while(dispatch_group_wait(group,DISPATCH_TIME_NOW)){
            [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
                                     beforeDate:[NSDate dateWithTimeIntervalSinceNow:3.0f]];
        }
    }
}    
}     

- (void)geolocateRoutePoint:(RoutePoint *)c {
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
NSString *addressString = [NSString stringWithFormat:@"%@,%@ %@ %@ %@",
                           c.addressName,
                           c.addressNumber,
                           @"SOME CITY",
                           @"SOME STATE",
                           @"SOME COUNTRY"];

[geocoder geocodeAddressString:addressString
             completionHandler:^(NSArray *placemarks, NSError *error) {

                 if (error) {
                     NSLog(@"Geocode failed with error: %@", error);
                     return;
                 }

                 if (placemarks && placemarks.count > 0)
                 {
                     CLPlacemark *placemark = placemarks[0];

                     CLLocation *location = placemark.location;
                     c.addressLatitude =  [NSNumber numberWithDouble:location.coordinate.latitude];
                     c.addressLongitude = [NSNumber numberWithDouble:location.coordinate.longitude];
                 }
             }];
}

【问题讨论】:

    标签: ios objective-c geocoding delay


    【解决方案1】:

    嗯,也许只是在你的 GCD 中使用“afterDelay”,而不是 NSDate。

    [self performSelector:@selector(geolocateGroup) 
    withObject:@"Grand Central Dispatch" afterDelay:3.0];
    

    【讨论】:

    • 嗨@Droidnoid。感谢您的建议。使用 performSelector 和 afterDelay 结果是一样的:只有 50 个地址获得了纬度和经度信息。其他地址出现错误:kCLErrorDomain 错误 2。我认为我的代码在“一次”中触发 geolocateRoutePoint 方法 150 次,而不是在 3 秒的间隔内一个一个触发。这个performSelector的用法给了我一个思路!现在它可以工作了。谢谢!我会在稍后发布答案。
    • @Droidnoid:当它接受一个数组时,你为什么要向该选择器传递一个字符串 (@Grand Central Dispatch)?
    • 很好的提示,但 1.5 秒就足够了
    【解决方案2】:

    我在回复 Droidnoid 时想到了一个主意,它可以工作。

    这里是交易:递归。地理编码完成后,它会以 3 秒的时间间隔开始一个新的地理编码请求。我现在变成了只有一种方法。

    ...
    NSMutableArray *arrayOfRoutePoints = [[NSMutableArray alloc] initWithArray:fetchedObjects];
    [self geolocateRoutePoint:arrayOfRoutePoints];
    ...
    
    - (void)geolocateRoutePoint:(NSMutableArray *)mutableArrayWithRoutePoints {
    
    if ([mutableArrayWithRoutePoints count] > 0) {
        RoutePoint *c = [mutableArrayWithRoutePoints objectAtIndex:0];
    
        if ([c.addressLatitude intValue] == 0) {
            CLGeocoder *geocoder = [[CLGeocoder alloc] init];
            NSString *addressString = [NSString stringWithFormat:@"%@,%@ %@ %@ %@",
                                       c.addressName,
                                       c.addressNumber,
                                       @"SOME CITY",
                                       @"SOME STATE",
                                       @"SOME COUNTRY"];
    
            [geocoder geocodeAddressString:addressString
                         completionHandler:^(NSArray *placemarks, NSError *error) {
    
                             [mutableArrayWithRoutePoints removeObjectAtIndex:0];
                             [self performSelector:@selector(geolocateRoutePoint:)
                                        withObject:mutableArrayWithRoutePoints afterDelay:3.0];
    
                             if (error) {
                                 NSLog(@"Geocode failed with error: %@", error);
                                 return;
                             }
    
                             if (placemarks && placemarks.count > 0)
                             {
                                 CLPlacemark *placemark = placemarks[0];
    
                                 CLLocation *location = placemark.location;
                                 c.addressLatitude =  [NSNumber numberWithDouble:location.coordinate.latitude];
                                 c.addressLongitude = [NSNumber numberWithDouble:location.coordinate.longitude];
    
                                 // Saving the context here after getting geocode.
                                 // Definitely not the best place to save the context. 
                                 // I will move this later to another place
                                 NSError *error = nil;
                                 if (![self.managedObjectContext save:&error]) {
                                     NSLog(@"Error! %@", error);
                                 }
                             }
                         }];
        }
        else
        {
            [mutableArrayWithRoutePoints removeObjectAtIndex:0];
            [self performSelector:@selector(geolocateRoutePoint:)
                       withObject:mutableArrayWithRoutePoints];
        }
    }
    }
    

    【讨论】:

    • 我认为这没有考虑到这样一个事实,即通过非常快的连接,您仍然可以轻松地以每分钟超过 50 个地理编码结束。为什么不直接使用NSTimer 来遍历您的地址字符串,直到一个都没有?
    • 问题不在于连接速度非常快,而在于我之前所说的地理编码时每分钟 50 个请求的限制。我认为 Apple 这样做的目的是防止滥用在短时间内进行大量地理编码并导致服务器过载。
    猜你喜欢
    • 2014-01-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-20
    • 1970-01-01
    • 2018-04-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多