7

緯度と経度を知る必要がある約 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];
}

ありがとうございました!

4

2 に答える 2

17

大きなセットをすぐにジオコーディングすることはできません。iOSはあなたを抑制します。iOS では一度に 50 個のジオコードに制限されており、「時間」要素は不明です。

私も同様の問題を抱えていましたが、ジオコーディング データを順番にユーザーに提示するだけで時間がかかるため、すべてのジオコーディングをキューに入れました。

事実上、25 のチャンクをジオコーディングします。それぞれの結果の間に約 0.5 秒の間隔で一度にユーザー 1 に結果を表示します。表示するものが 4 つ未満になったら、次の 25 をジオコーディングします。これは、すべてがジオコーディングされるまで (私の場合は無期限に) 続きます。

一度にすべてをジオコーディングする必要がある場合は、ジオコーディングを各チャンク間の遅延と一緒に連鎖させ、完了するまで何らかのビジー インジケーターを表示する必要があります。これは、ジオコーディングの大規模なセットでしばらく時間がかかる可能性があります.

于 2012-05-16T13:59:50.123 に答える
8

答えは、AppleのジオコーダーのTOSに違反しているということです。

CLGeocoderのドキュメントから。

アプリケーションは、ジオコーディングの使用方法を意識する必要があります。このクラスを効果的に使用するための経験則は次のとおりです。

1つのユーザーアクションに対して最大で1つのジオコーディングリクエストを送信します。ユーザーが同じ場所のジオコーディングを含む複数のアクションを実行する場合は、アクションごとに個別のリクエストを開始するのではなく、最初のジオコーディングリクエストの結果を再利用します。ユーザーの現在地を自動的に更新する場合(ユーザーが移動しているときなど)、ユーザーがかなりの距離を移動し、妥当な時間が経過した後にのみ、新しいジオコーディング要求を発行します。たとえば、一般的な状況では、1分間に複数のジオコーディングリクエストを送信しないでください。ユーザーに結果がすぐに表示されないときにジオコーディングリクエストを開始しないでください。たとえば、アプリケーションが非アクティブであるかバックグラウンドにある場合は、リクエストを開始しないでください。

Appleは、応答の提供を停止したり、アプリを完全に切断したり、開発者アカウントを取り消したりする権利を十分に有しています。

このような多数の住所を迅速に処理する必要がある場合は、Factual for PointsofInterestやDataScienceToolkitなどの郵便住所や地理的地域向けのサービスの利用を検討する必要があります。


アップデート

これは、 Places API-ResolveのAPIドキュメントです。これは、Factualのplacesジオコーダーです。


アップデート2

これは、DataScienceToolkitのロケーションジオコーダーであるStreetAddresstoCoordinatesのAPIです。

于 2012-05-16T14:18:18.703 に答える