緯度と経度を知る必要がある約 200 の住所の大規模なセットを取得しました。アドレスを解析するメソッドを作成しました。現在、これらのアドレスの座標を を使用して取得しようとしていますCLGeocoder
。
私の現在のアプローチは、ジオコーダーを並行して作成し、それらに魔法をかけてもらうことです。それぞれが別々のスレッドを取っているように見えることに気付きました。(そのため、ある時点で最大 100 のスレッドが表示されました)。
私が直面している問題は、ある時点 (約 50 の住所の後) で、ジオコードが場所のマークを返さなくなり、
NSLog(@"Address not recognized: *%@*",[htc objectForKey:kAddressKey]);
呼ばれます。これはスレッド数の制限ですか、それとも組み込みの CLGeocoder の制限ですか? ジオコーダーを適切にクリーンアップしておらず、ある種の自動解放ステートメント (ARC) が必要なのでしょうか?
-(void)geocodeArray:(NSMutableArray*)array {
NSMutableDictionary* htc = nil;
objectsToGeocode = array.count;
NSDictionary *htcDictionary =nil;
for (int i = 0; i<array.count;i++) {
htcDictionary = [array objectAtIndex:i];
//create an updated dictionary that would hold the reverse geocoding location
htc = [[NSMutableDictionary alloc] initWithDictionary:htcDictionary];
NSLog(@"geocoding: %@",[htc objectForKey:kAddressKey]);
CLGeocoder* geoCoder = [[CLGeocoder alloc] init];
[geoCoder geocodeAddressString:[htc objectForKey:kAddressKey] completionHandler:^(NSArray *placemarks, NSError *error) {
if(placemarks.count>0)
{
NSLog(@"Found placemarks for %@",[htc objectForKey:kAddressKey]);
CLPlacemark* placemark = [placemarks objectAtIndex:0];
MyLocation *annotation = [[MyLocation alloc]
initWithName:[htcDictionary objectForKey:kNameKey]
address:[htcDictionary objectForKey:kAddressKey]
coordinate:placemark.location.coordinate] ;
annotation.faxNumber = [htc objectForKey:kFaxKey];
annotation.phoneNumber = [htc objectForKey:kPhoneKey];
annotation.website = [htc objectForKey:kWebsiteKey];
annotation.type = [htc objectForKey:kFacilityTypeKey];
[_mapView addAnnotation:annotation];
double placemarkToUserDistance = [self._mapView.userLocation.location distanceFromLocation:placemark.location] ;
//convert distance to miles
placemarkToUserDistance =placemarkToUserDistance/ 1000/ kKilometersPerMile;
[htc setObject:[NSNumber numberWithDouble:placemarkToUserDistance] forKey:kDistanceToUserKey];
[htc setObject:[NSNumber numberWithDouble:placemark.location.coordinate.latitude] forKey:kLatitudeKey];
[htc setObject:[NSNumber numberWithDouble:placemark.location.coordinate.longitude] forKey:kLongitudeKey];
NSAssert([htc objectForKey:kLatitudeKey]!=nil,@"kLatitudeKey is not saved!");
NSAssert([htc objectForKey:kLongitudeKey]!=nil,@"kLongitudeKey is not saved!");
}else {
NSLog(@"Address not recognized: *%@*",[htc objectForKey:kAddressKey]);
}
[self.dataSource addObject:htc];
if(++geocodingCount >=objectsToGeocode){
NSLog(@"%@",self.dataSource);
[self saveGeocoding];
}
} ];
// [temp addObject:htcDictionary];
}
}
これがスレッドの問題かどうかをテストするために、このメソッドを作成しました。このメソッドは、大きなデータセットを 5 つの配列に分割し、それらをチャンクでジオコーディングしようとします。最初のリクエストと 2 番目のリクエストの一部が通過することに気付きました。しかし、マジック ナンバー (~50) に達すると、ジオコーディングは停止します。
何が起こっているのかについてのアイデアはありますか?これは、Apple がジオコーディング操作の数に課した制限ですか? リクエスト間の遅延を増やすか、アプリを 5 回別々に実行して、結果を手作業でまとめる必要がありますか?
-(void)geocodeDatasource
{
//I'm trying to build a file with coordinates of addresses and include it with the app
geocodingCount = 0;
self.dataSource = [[NSMutableArray alloc] initWithCapacity:self.arrayForGeocodingInitialJSON.count+5];
haveToEmailInitialResults = YES;
//attempt to geocode in batches
float numberOfArrays = 5.0;
NSMutableArray* array1 = [[NSMutableArray alloc] initWithCapacity:arrayForGeocodingInitialJSON.count/numberOfArrays];
NSMutableArray* array2 = [[NSMutableArray alloc] initWithCapacity:arrayForGeocodingInitialJSON.count/numberOfArrays];
NSMutableArray* array3 = [[NSMutableArray alloc] initWithCapacity:arrayForGeocodingInitialJSON.count/numberOfArrays];
NSMutableArray* array4 = [[NSMutableArray alloc] initWithCapacity:arrayForGeocodingInitialJSON.count/numberOfArrays];
NSMutableArray* array5 = [[NSMutableArray alloc] initWithCapacity:arrayForGeocodingInitialJSON.count/numberOfArrays];
for(int i = 0 ;i<arrayForGeocodingInitialJSON.count;i++)
{
id object = [arrayForGeocodingInitialJSON objectAtIndex:i];
if(i<arrayForGeocodingInitialJSON.count*(1/numberOfArrays))
{
[array1 addObject:object];
}else if(i>=arrayForGeocodingInitialJSON.count/numberOfArrays && i<arrayForGeocodingInitialJSON.count*(2/numberOfArrays))
{
[array2 addObject:object];
}else if(i>=arrayForGeocodingInitialJSON.count*(2/numberOfArrays) && i<arrayForGeocodingInitialJSON.count*(3/numberOfArrays))
{
[array3 addObject:object];
}else if(i>=arrayForGeocodingInitialJSON.count*(3/numberOfArrays) && i<arrayForGeocodingInitialJSON.count*(4/numberOfArrays))
{
[array4 addObject:object];
}else if(i>=arrayForGeocodingInitialJSON.count*(4/numberOfArrays) && i<arrayForGeocodingInitialJSON.count)
{
[array5 addObject:object];
}
}
//simple delays eliminate the need for extra variables and notifications
[self geocodeArray:array2];
[self performSelector:@selector(geocodeArray:) withObject:array1 afterDelay:15];
[self performSelector:@selector(geocodeArray:) withObject:array3 afterDelay:30];
[self performSelector:@selector(geocodeArray:) withObject:array4 afterDelay:45];
[self performSelector:@selector(geocodeArray:) withObject:array5 afterDelay:45];
}
ありがとうございました!