web-dev-qa-db-ja.com

UISearchBarでMKMapViewを検索する方法は?

Apple "Maps"アプリケーション(iPhone、iPod Touch、iPadに含まれる)などの同様の検索機能が必要なアプリケーションがあります。

問題の機能を実行するのは難しいことではありませんが、検索バーに番地を入力し、その住所または実際に地図を移動するのに役立つ何かの座標を取得する方法については本当にわかりませんその場所の中心。

Appleは「アドレス検索APIメソッド」を提供しますか?またはGoogleマップAPIを直接使用する必要がありますか?

どうすればいいのか聞きたいです。

42
Goles

わかりました、私自身の質問に答えるために:

前述したように、最善の方法はGoogle Maps APIを使用することです。これは多くの形式をサポートしますが、いくつかの理由でJSONを選択しました。

そこで、Googleマップに対してJSONクエリを実行し、クエリの座標を取得する手順を次に示します。すべての正しい検証が行われるわけではなく、これは概念実証にすぎないことに注意してください。

1)iPhone用のJSONフレームワーク/ライブラリをダウンロードしてください、いくつかあります、私は これ と行くことを選択しました、さらにいくつかの商用アプリケーションがそれを使用しているようです。それをプロジェクトに追加します(手順 here )。

2)Googleマップに住所を照会するには、次のようなリクエストURLを作成する必要があります: http://maps.google.com/maps/geo?q=Paris+France

このURLは、クエリ「Paris + France」のJSONオブジェクトを返します。

3)コード:

//Method to handle the UISearchBar "Search", 
- (void) searchBarSearchButtonClicked:(UISearchBar *)theSearchBar 
{
    //Perform the JSON query.
    [self searchCoordinatesForAddress:[searchBar text]];

    //Hide the keyboard.
    [searchBar resignFirstResponder];
}

UISearchBar検索を処理した後、Googleマップにリクエストを行う必要があります。

- (void) searchCoordinatesForAddress:(NSString *)inAddress
{
    //Build the string to Query Google Maps.
    NSMutableString *urlString = [NSMutableString stringWithFormat:@"http://maps.google.com/maps/geo?q=%@?output=json",inAddress];

    //Replace Spaces with a '+' character.
    [urlString setString:[urlString stringByReplacingOccurrencesOfString:@" " withString:@"+"]];

    //Create NSURL string from a formate URL string.
    NSURL *url = [NSURL URLWithString:urlString];

    //Setup and start an async download.
    //Note that we should test for reachability!.
    NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];
    NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];

    [connection release];
    [request release];
}

もちろん、GoogleMapsサーバーの応答を処理する必要があります(注:多くの検証が欠落しています)

//It's called when the results of [[NSURLConnection alloc] initWithRequest:request delegate:self] come back.
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data 
{   
    //The string received from google's servers
    NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

    //JSON Framework magic to obtain a dictionary from the jsonString.
    NSDictionary *results = [jsonString JSONValue];

    //Now we need to obtain our coordinates
    NSArray *placemark  = [results objectForKey:@"Placemark"];
    NSArray *coordinates = [[placemark objectAtIndex:0] valueForKeyPath:@"Point.coordinates"];

    //I put my coordinates in my array.
    double longitude = [[coordinates objectAtIndex:0] doubleValue];
    double latitude = [[coordinates objectAtIndex:1] doubleValue];

    //Debug.
    //NSLog(@"Latitude - Longitude: %f %f", latitude, longitude);

    //I zoom my map to the area in question.
    [self zoomMapAndCenterAtLatitude:latitude andLongitude:longitude];

    [jsonString release];
}

最後に、地図をズームする機能。これは今では些細なことです。

- (void) zoomMapAndCenterAtLatitude:(double) latitude andLongitude:(double) longitude
{
    MKCoordinateRegion region;
    region.center.latitude  = latitude;
    region.center.longitude = longitude;

    //Set Zoom level using Span
    MKCoordinateSpan span;
    span.latitudeDelta  = .005;
    span.longitudeDelta = .005;
    region.span = span;

    //Move the map and zoom
    [mapView setRegion:region animated:YES];
}

JSONの部分を理解するのは本当に苦痛だったので、これが誰かの助けになることを願っています。ライブラリは私の意見ではあまり文書化されていませんが、それでも非常に良いです。

編集:

@Leoの質問のため、1つのメソッド名を「searchCoordinatesForAddress:」に変更しました。この方法は概念実証としては良いと言わざるを得ませんが、大きなJSONファイルをダウンロードする場合は、NSMutableDataオブジェクトに追加して、Googleサーバーへのすべてのクエリを保持する必要があります。 (HTTPクエリがばらばらに来ることを覚えてください。)

39
Goles

これがおそらく最も簡単な方法です。ジオコーディングにAppleサーバーを使用します。時々、Appleサーバーはgoogleよりも良い応答を提供します。そしてすぐに(IOS 6.1 )Googleマップは完全にIOSから除外されるため、アプリがりんごが提供する機能の内部にとどまるのは良いことです。

-(void)searchBarSearchButtonClicked:(UISearchBar *)theSearchBar
{
    [theSearchBar resignFirstResponder];
    CLGeocoder *geocoder = [[CLGeocoder alloc] init];
    [geocoder geocodeAddressString:theSearchBar.text completionHandler:^(NSArray *placemarks, NSError *error) {
        //Error checking

        CLPlacemark *placemark = [placemarks objectAtIndex:0];
        MKCoordinateRegion region;
        region.center.latitude = placemark.region.center.latitude;
        region.center.longitude = placemark.region.center.longitude;
        MKCoordinateSpan span;
        double radius = placemark.region.radius / 1000; // convert to km

        NSLog(@"[searchBarSearchButtonClicked] Radius is %f", radius);
        span.latitudeDelta = radius / 112.0;

        region.span = span;

        [theMapView setRegion:region animated:YES];
    }];
}
56
user1466453

IOS 9に適合したSwiftバージョン:

let geocoder = CLGeocoder()
geocoder.geocodeAddressString(addressString) { (placemarks, error) in

    if let center = (placemarks?.first?.region as? CLCircularRegion)?.center {

        let region = MKCoordinateRegion(center: center, span: MKCoordinateSpanMake(0.02, 0.02))
        self.mapView.setRegion(region, animated: true)
    }
}

user1466453の回答に基づきます。

2
Eric

このリンクは、地域を検索する場合に役立ちます。

NSMutableString *urlString = [NSMutableString stringWithFormat:@"http://maps.google.com/maps/geo?q=%@?output=json",inAddress];

あなたが通りを検索したい場合、これはcorectリンクです

NSMutableString *urlString = [NSMutableString stringWithFormat:@"http://maps.google.com/maps/geo?q=%@&output=json",inAddress];

注意 2番目の?&

2
Vali

他の誰かが同じ問題を抱えている場合、リンクはこちらです: https://github.com/stig/json-framework/ スクロールダウンしてSBJson

また、アプリが使用する前にすべてのデータを取得するためのコードもあります。デリゲートメソッド 'did receive data'は、ダウンロード可能なデータに可変データオブジェクトを追加するので注意してください。

MR GANDOS searchCoodinatesMETHOD AS IT IS AS IT WORKS WELL

- (void) searchCoordinatesForAddress:(NSString *)inAddress
{
    //Build the string to Query Google Maps.
    NSMutableString *urlString = [NSMutableString stringWithFormat:@"http://maps.googleapis.com/maps/api/geocode/json?address=%@&sensor=false",inAddress];

    //Replace Spaces with a '+' character.
    [urlString setString:[urlString stringByReplacingOccurrencesOfString:@" " withString:@"+"]];

    //Create NSURL string from a formate URL string.
    NSURL *url = [NSURL URLWithString:urlString];

    //Setup and start an async download.
    //Note that we should test for reachability!.
    NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];

    NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];

    [connection release];
    [request release];
}

//ステップ1 //この1つIS重要なのは、応答としてASが可変データオブジェクトを作成するときIS

-(void)connection:(NSURLConnection*)connection didReceiveResponse:(NSURLResponse*)response
{
    if (receivedGeoData) 
    {
        [receivedGeoData release];
        receivedGeoData = nil;
        receivedGeoData = [[NSMutableData alloc] init];
    }
    else
    {
        receivedGeoData = [[NSMutableData alloc] init];
    }

}

///ステップ2 //この1つISデータオブジェクトにデータを追加する際に重要

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data 
{   
    [receivedGeoData appendData:data]; 
}

//ステップ3 ...... //これですべてのデータを使用できるようになりました

- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    NSString *jsonResult = [[NSString alloc] initWithData:receivedGeoData encoding:NSUTF8StringEncoding];
    NSError *theError = NULL;
    dictionary = [NSMutableDictionary dictionaryWithJSONString:jsonResult error:&theError];

    NSLog(@"%@",dictionary);

    int numberOfSites = [[dictionary objectForKey:@"results"] count];
    NSLog(@"count is %d ",numberOfSites);      
}

-(void)connection:(NSURLConnection*)connection didFailWithError:(NSError*)error
{
    // Handle the error properly
}
2
timv

GoogleのAPIサービスを使用して、テキスト検索文字列から緯度/経度の座標を取得できます。結果が関連するように、ユーザーの現在の場所を必ず渡してください。この質問への回答をお読みください: MKMapViewでビジネスの場所を検索および表示

1
William Denniss