2

Core Data 内にいくつかの住所があり、それらの緯度と経度を取得する必要があります。アドレスの数は約 150 から 200 です。スレッドiPhone iOS5 CLGeocoder how to geocode a large (200) set of addresses? で、iOS が 1 分あたり 50 ジオコードに制限していることを読みました。. その 1 分間に 50 のジオコードを起動し、その後さらに 50 のジオコードを起動する方法を知る必要があります。コードを実行すると、次のエラーが表示されます。

ジオコードが次のエラーで失敗しました: エラー Domain=kCLErrorDomain Code=2 "The operation could not be completed. (kCLErrorDomain error 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];
                 }
             }];
}
4

2 に答える 2

1

うーん、NSDate の代わりに、GCD で「afterDelay」を使用するだけかもしれません。

[self performSelector:@selector(geolocateGroup) 
withObject:@"Grand Central Dispatch" afterDelay:3.0];
于 2013-01-28T19:57:29.307 に答える
1

Droidnoid に返信しているときにアイデアを思いついたのですが、うまくいきました。

これが取り引きです:再帰。ジオコードが完了すると、3 秒間隔で新しい 1 つのジオコード リクエストが開始されます。私は今、唯一の方法になるように変更しました。

...
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];
    }
}
}
于 2013-01-28T23:40:51.470 に答える