前回の対応で、1つ目の問題はクリアした。今回は、2つ目の問題に対応したい。
- 住所として道路名がとれてしまう
- 逆ジオコーディングに時間がかかり操作がブロックされることがある
当初didUpdateToLocationの中で、Google Maps APIを利用した逆ジオコーディングを行っていた。この処理は同期処理で、大抵はすぐに結果が返ってくるので問題ないが、たまに時間がかかることがあり、UI操作の妨げとなっていることがわかった。
こんな感じ。
// URLを作成する NSString *urlstring = [NSString stringWithFormat: @"http://maps.google.com/maps/api/" @"geocode/json?latlng=%f,%f&sensor=false", coordinate.latitude, coordinate.longitude]; NSURL *url = [NSURL URLWithString: urlstring]; // URLリクエストから結果受取まで // この処理が同期処理 NSString *result = [NSString stringWithContentsOfURL: url encoding: NSUTF8StringEncoding error: nil]; // JSON形式の取得結果からディクショナリを作成 NSDictionary *addresses = [result JSONValue];
まず最初に思いついたのは、CLLocationManagerのdistanceFilterの値を大きくして、位置情報の更新頻度を落とせばよいのではないか?ということで、やってみた。
っが、根本的な解決にはならず、玉砕。
結局、非同期処理を実装することにした。
また、位置情報が更新されるたびに非同期リクエストを発行するのも無駄に思えたので、viewDidLoadの中で、10秒毎のタイマを仕込む事に。
// 逆ジオコーディング処理を定期的に行うようにタイマーを設定 timer = [NSTimer scheduledTimerWithTimeInterval: 10.0f target: self selector: @selector(timerAction:) userInfo: nil repeats: YES];
timerActionの中で、非同期リクエストを発行する。
// URLを作成 NSString *urlstring = [NSString stringWithFormat: @"http://maps.google.com/maps/api/" @"geocode/json?latlng=%f,%f&sensor=false", coordinate.latitude, coordinate.longitude]; NSURL *url = [NSURL URLWithString: urlstring]; // ここまでは、同期処理と同様 // URLリクエストを作成 NSURLRequest *request = [NSURLRequest requestWithURL: url]; // URLコネクションを作成 connection = [[NSURLConnection alloc] initWithRequest: request delegate: self];
これで、非同期リクエストの発行は完了。後は、デリゲートで処理をする。
// 非同期通信デリゲート 初回ヘッダー受取処理 - (void)connection: (NSURLConnection *)_connection didReceiveResponse: (NSURLResponse *)response { // データの初期化処理など } // 非同期通信デリゲート 繰り返しデータ受取処理 // このデリゲートは、データ量に応じて何回も呼ばれる - (void)connection: (NSURLConnection *)_connection didReceiveData: (NSData *)data { // データをためる } // 非同期通信デリゲート エラー処理 - (void)connection: (NSURLConnection *)_connection didFailWithError: (NSError *)error { // エラー処理 } // 非同期通信デリゲート 受取完了 - (void)connectionDidFinishLoading: (NSURLConnection *)_connection { NSString *result = [[NSString alloc] initWithData: ためたデータ encoding: NSUTF8StringEncoding]; // JSON形式の取得結果からディクショナリを作成 NSDictionary *addresses = [result JSONValue]; // 前回紹介した住所文字作成部分がここ :(以下省略) }
この方法で、UI操作がブロックされなくなり、サクサク動くようになった。
また、タイマ処理に変更したことで、位置情報の更新頻度を上げても問題なく動作することもわかった。
いいね!これで思い通りに動くようになった。