[iOS]地図(住所検索) | Cocoa練習帳

[iOS]地図(住所検索)

地図アプリケーションといえば住所から地図を検索する機能を期待すると思うが、住所から位置情報を取得する機能はBing Maps iOS SDKに含まれていない。特に、Bingにこだわる必要はないが、せっかくなので、Bing Maps REST Servciesを使うことにした。


以下が検索要求を出すコードだ。


- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar
{
    if ((searchBar.text == nil) || (searchBar.text.length <= 0))    return;
    self.data = [[NSMutableData alloc] init];
    NSString    *bingMapsKey = [[NSBundle mainBundle] objectForInfoDictionaryKey: @"BingMapsKey"];
    NSString    *query = (__bridge NSString *)CFURLCreateStringByAddingPercentEscapes(NULL,
                                                                                     (CFStringRef)searchBar.text,
                                                                                     NULL,
                                                                                     (CFStringRef)@"!*%'();:@&=+-$,/?%#[]~",
                                                                                     kCFStringEncodingUTF8);
    NSString    *url = [[NSString alloc] initWithFormat:@"http://dev.virtualearth.net/REST/v1/Locations?query=%@&key=%@&c=%@-%@",
                        query,
                        bingMapsKey,
                        [[NSLocale currentLocale] objectForKey:NSLocaleLanguageCode],
                        [[NSLocale currentLocale] objectForKey:NSLocaleCountryCode]];
    NSLog(@"url: %@", url);
    NSURLRequest    *urlRequest = nil;
    urlRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:url]];
    [NSURLConnection connectionWithRequest:urlRequest delegate:self];
    [UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
}

cパラメータにja-jpを指定しないと、日本語の住所が上手く検索できない。当初、入力されたテキストの言語に対応したcパラメータの指定を考えてみたが、よい考えが思い浮かばなかったので、止めた。


応答結果から緯度経度を取り出して、その位置を表示するコードだ。


- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
    
    NSError *error = nil;
    NSDictionary    *content = [NSJSONSerialization JSONObjectWithData:self.data options:NSJSONReadingAllowFragments error:&error];
    NSLog(@"content:%@", content);
    
    if (content) {
        NSArray *resourceSets = [content objectForKey:@"resourceSets"];
        NSLog(@"resourceSets:%@", resourceSets);
        
        if (resourceSets) {
            NSDictionary    *resource = [resourceSets objectAtIndex:0];
            NSLog(@"resource:%@", resource);
            
            if (resource) {
                NSArray    *resources = [resource objectForKey:@"resources"];
                NSLog(@"resources:%@", resources);
                
                if ((resources) && (0 < [resources count])) {
                    resource = [resources objectAtIndex:0];
                    NSLog(@"resource:%@", resource);
                    
                    if (resource) {
                        NSDictionary    *point = [resource objectForKey:@"point"];
                        NSLog(@"point:%@", point);
                        
                        if (point) {
                            NSArray *coordinates = [point objectForKey:@"coordinates"];
                            NSLog(@"coordinates:%@", coordinates);
                            
                            if ((coordinates) && (0 < [coordinates count])) {
                                NSString    *latitude = [coordinates objectAtIndex:0];
                                NSString    *longitude = [coordinates objectAtIndex:1];
                                NSLog(@"latitude:%@", latitude);
                                NSLog(@"longitude:%@", longitude);
                                
                                if ((latitude) && (longitude)) {
                                    BMCoordinateRegion  newRegion;
                                    newRegion.center.latitude = [latitude floatValue];
                                    newRegion.center.longitude = [longitude floatValue];
                                    newRegion.span.latitudeDelta = 0.005;
                                    newRegion.span.longitudeDelta = 0.005;
                                    
                                    [self.mapView setRegion:newRegion animated:YES];
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    
    if ([self.searchBar canResignFirstResponder])
        [self.searchBar resignFirstResponder];
}

条件分が深くなっているのは格好が悪いが、サンプルなので勘弁して欲しい。


探偵物語の工藤探偵事務所の住所を表示してみた。


BitzMaps


ソースコード
GitHubからどうぞ。

関連情報

【Cocoa練習帳】
http://ameblo.jp/bitz/(ミラー・サイト)