2

Google の Geocode API を使用して緯度/経度に変換する必要がある住所の配列があります。正しい接続 URL を形成する Google Geocode URL に住所と都市を入力しています。

基本的に、for ループを使用して複数の NSURLConnection リクエストを作成し、複数の応答を返すことができるようにしたいと考えています。

-(void)setString{
 for (int i = 0; i < [businessArray count]; i ++)
{         
NSString *address = [addressArray objectAtIndex:0];
NSString *city = [locationDict valueForKey:@"city"];
NSString *geocodeURL = [NSString stringWithFormat:@"http://maps.googleapis.com/maps/api/geocode/json?address=%@,+%@,&sensor=true", address, city];
    geocodeURL = [geocodeURL stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
        NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:geocodeURL]
                                                           cachePolicy:NSURLRequestUseProtocolCachePolicy
                                                       timeoutInterval:10];
    NSLog(@"%@", request);
    geoCodeConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];


    if (geoCodeConnection)
    {
        responseData = [NSMutableData data];
        connectionIsActive = YES;
        NSLog(@"connection active");

    } else {
        NSLog(@"connection failed");
        connectionIsActive = NO;
    }

}
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{


    NSString *responseString    = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
    NSError *jsonError          = nil;

    SBJsonParser *json          = [[SBJsonParser alloc] init];

    NSDictionary *parsedJSON    = [json objectWithString:responseString error:&jsonError];

    NSString *lat= [[[[parsedJSON valueForKey:@"results"] valueForKey:@"geometry"] valueForKey:@"location"] valueForKey:@"lat"];
    NSString *lng= [[[[parsedJSON valueForKey:@"results"] valueForKey:@"geometry"] valueForKey:@"location"] valueForKey:@"lng"];

    NSLog(@"lat = %@ long= %@", lat, lng);
    connectionIsActive          = NO;
    [geoCodeLatArray addObject:lat];
    [geoCodeLngArray addObject:lng];
    NSLog(@"geoCodeArrayLat: %@", geoCodeLatArray);


}

現在、コードは最後の住所の緯度と経度のみを返します。複数のリクエストを送信し、JSON で複数のレスポンスを返すにはどうすればよいですか?

4

3 に答える 3

1

リクエストを実行し、結果が利用可能になったときに呼び出される完了ブロックを持つ非同期メソッドを使用して、問題に取り組むことができます。この完了ブロックは、接続要求の結果であるパラメーター結果を提供します。

このメソッドは次のように宣言できます。

typedef void (^completion_block_t) (id result);

- (void) fetchGeoCoordinateForAddress:(NSString*)address 
                    completionHandler:(completion_block_t)completionHandler;

たとえば、リクエストが成功した場合、ブロック内のパラメータ結果はレスポンス データの JSON 表現になります。それ以外の場合、結果はエラーを示す NSError オブジェクトです。ただし、正確な詳細はメソッドの実装方法によって異なりますfetchGeoCoordinateForAddress:completionHandler:

これで、次のようにループをセットアップできます。

for (NSString* address in addresses) 
{
    [self fetchGeoCoordinateForAddress:address completionHandler:^(id result) {
        if (![result isKindOfError:[NSError class]]) // check if result is an error
        {
            // Note: result is not nil and is a NSDictionary representation of JSON.

            // Retrieve the "location" from the response:
            NSDictionary* location = result[@"results"][@"geometry"][@"location"];

            // Multiple request can occur at the same time! Thus, we need to 
            // synchronize access to the result array "myLocations" through 
            // accessing it *exclusively and everywhere* on the main thread:
            dispatch_async(dispatch_get_main_queue(), ^{
                [self.myLocations addObject:location];
            });                
        }
        else {
            // got error
            DebugLog(@"ERROR: %@", result);
        }
    }
}

注: 実際のコードは、実際の JSON やその他の詳細によって若干異なる場合があります。

メソッドの実装に関してはfetchGeoCoordinateForAddress:completionHandler:、いくつかのオプションがあります。

  1. サード パーティのライブラリを使用して、シンプルな便利なラッパーを実装しますfetchGeoCoordinateForAddress:completionHandler:

  2. NSURLConnectionおよび応答データとその他の有用な状態情報を専用クラスにカプセル化する独自の「MyHTTPConnectionOperation」クラスを作成します。このクラスはstartメソッドを介してリクエストを非同期に実行し、完了ハンドラを持ちます。基本的に、サードパーティのネットワーク ライブラリはすべてこのアプローチを使用します。次に、ラッパーを実装します。

  3. NSURLConnection の非同期の便利なメソッドで十分であり、コンテキストで機能する場合は、それを使用してください。これは実装が最も速い方法ですが、柔軟性が最も低く、すべての場合に機能するとは限りません。

編集:

いくつかのヒント:

  • 可能であれば、NSJSONSerializationJSON の解析と Foundation 表現の作成に使用します。他のサードパーティ製ライブラリは、特別な要件がある場合にのみわずかな利点しかありません。たとえば、「NSData オブジェクトを使用したチャンク解析」が必要な場合などです。これは、ダウンロードと解析を同時に行いたい場合に役立ちます。または、Foundation 以外の表現を作成する必要があります。たとえば、C++ コンテナーを作成するか、SAX スタイルの解析を使用してモデルを直接作成する必要があります。または、ディスクに保存したい非常に大きな文字列を受け取っているため、パフォーマンスを向上させ、メモリを少なくする必要があります。NSJSONSerializationは最近非常に高速になったため、今日では「パフォーマンス」だけを議論するべきではありません。

  • リクエストのタイムアウトは、10 秒ほど短くはなりません。セルラー接続では、これは少なすぎます。デフォルトのままにしておきます。

  • 独自の「HTTPConnectionOperation」クラスを実装する予定がある場合は、非常に限定されたサンプルを Gist hereに掲載しました。これにより、すぐに始めることができます。

于 2013-07-08T09:28:28.767 に答える