Hatena::Groupiphone-dev

勢いでMacを買っちゃったんで iPhoneアプリ頑張って開発する

2010-03-25

CoreLocationの気まぐれ動作(その3)

| 01:47

コメントでxyzさんに頂いたアドバイスを参考に改良するも、最新の位置情報を拾ってくれない状況は変わらず。

そこで、デフォルトのマップアプリを参考に歩きまわってた。

計測してスリープ → 場所を移動してまた計測と繰り返す。すると、10秒程度では最新の位置情報を拾ってくれないケースが多発した。

  • "品川"
  • "新宿"
    • 新宿駅に到着。
    • そこで再度、地図アプリを表示させると、10秒足らずで画面上では地図が描きかえられる。
    • 見た目には「最新の情報を取得しました」といった挙動なのだが、表示されるのは、なぜか品川周辺の地図。
    • 30秒ほどすると、新宿駅周辺の地図が表示される。

信頼できる位置情報を拾うためには、だいたい30秒程度?の時間が必要だということが明らかになった。

デフォルトの地図アプリでも、こうした挙動なのだから、これはもうシステム側の仕様だろう。

また、来月当たりから時間を作ってアプリ改良に取り組みたい。

今はセキュリティ関係の調査と学習で手一杯。

xyzxyz2010/03/26 05:24都内ならWi-Fi をオンにするとよいのでは?

ID2ndID2nd2010/05/08 19:31コメントに気づかず申し訳ないですっ!!
今、手がけているアプリではWi-Fiが使えないところで使用することを想定しているので難しいですが、別の地図アプリを開発する際に試してみます。

ただ、私の行動圏内で言えば、Wi-Fiの電波が入る場所は限られてしまうために、移動しながら使用するアプリの場合は使いにくいかもです。

2010-03-07

CoreLocationの気まぐれ動作(その2)

| 01:13

先日書いた通り、CLLocationManagerクラスの挙動がアレで、ちょっと悩んでいる。

前回書いたのは「CLLocationManagerからのアップデート通知が必要以上に何回も送られてきて、デリゲートがそのたびに呼び出される」という話だった。

それに加えて「場所を移動し位置情報も変わっているはずなのに、通知される位置情報が更新されない」という問題に直面している。

例えば、5分おきに位置情報を計測するアプリを組み、新宿駅から東側(新宿駅新宿三丁目新宿御苑)に歩きながら動作させたとする。

《1回目》

1回目は新宿駅で計測が始まり、新宿駅近辺の緯度経度を入手することができる。これは正常に動作する。

《2回目:5分後》

その5分後、新宿三丁目付近に到着したタイミングで計測が開始されるとする。当然、新宿三丁目付近の緯度経度を入手できるはずだが、何故か新宿駅の緯度経度がデリゲートに送られてくるのである。

《3回目:10分後》

そのまま、5分間、新宿三丁目で立ち止まっていると、次の更新では新宿三丁目近辺の緯度経度を拾ってくれる。

5分間立ち止まらずに歩き続けて新宿御苑付近に到着していたなら、その時の更新では御苑付近の緯度経度を拾ってくれる。

つまり、2回に1回しか最新の位置情報を拾ってくれない。2回に1回はアップデート通知が届いても、届けられる位置情報は古い情報のままなのだ。

半日、あちこちうろうろして出た結果なので、偶然、位置情報を取得しにくい場所にいたため といった理由ではないだろう。*1

なぜなんだろう?そういう仕様なのだろうか?

*1:もしそうした理由であっても、didUpdateToLocationではなく、didFailWithErrorが呼び出されてしかるべきなので、いずれにせよ納得できないのだが

xyzxyz2010/03/08 03:15horizontalAccuracyを調べるといいんじゃなかったっけ。何回かdidUpdateToLocationが呼ばれて精度が上がっていくらしい。新宿あたりはノイズが多くて精度あがらないかも。

ID2ndID2nd2010/03/08 22:47!! なるほど…CLLocationクラスの horizontalAccuracyプロパティを調べて、精度の低い情報を落としていけばいいんですね。早速やってみます!

2010-03-06

CoreLocationの気まぐれ動作

| 02:45

悩んでいるのは二箇所。

1つ目、CoreLocationManagerが位置情報を拾いすぎる。

「位置情報を取得したよー」の時に呼び出されるのがdidUpdateToLocationのメソッド(didUpatalocationManager:didUpdateToLocation:fromLocation:)

ところが、一回、位置情報取得してこいと掛け声(startUpdatingLocation)を掛けると、このメソッドがなぜか何度も呼び出される。


CoreLocationManagerに関しては、こちらのページに簡潔にまとめられているようなので、参考にしてみる。

CLLocationで現在位置を取得する: iPhoneアプリ開発備忘録

すると、

didUpdateToLocationメソッドは、Locationのデータがアップデートした際に呼ばれるので、複数回呼ばれることがある。従って、このメソッドの後続処理で画面遷移などを行う場合は、アップデート通知を1回のみにする必要がある。その実装は、locationManagerメソッド内でstopUpdatingLocationを呼び出せばよい。

と書いてある。なるほど。

でも、こちらで試す限りstopUpdatingLocationのメッセージを出しても、didUpdateToLocationのメソッドが呼び出されている。

(ちなみに、stopUpdatingLocationを使った時には2回呼び出され、使わない時には3回呼び出されている。)


なぜ?

うちんとこのiPhoneは、そんなに位置測りたいの?計測が好きなの?

電波他の環境によって位置情報を計測しにくい、取得に時間がかかるという状況は予想していたけど、その逆は予想外だわ。

GPS衛星は、うちの上空10mくらいのところを飛んでのかもしれない。

ひとまず、センサーが働きすぎて位置情報を一度に何度も持ってくることもある という前提でアプリを書き直した。

ちょっと腑に落ちないところもあるけど。


2つ目、Objective-C + Cocoaの経験値が低い。

経験値が足りないため、やはり作業効率が低い。

先日も、単純なポカミスが原因の動作不良が起きたのだけど、原因がなかなか分からず難航した。

たしか、こんなケース。

  UILabel *label = ほげほげ

  label = @"foofoo"; // ← label.textとするところなのだが、.textを書き落とした。

こうしたケースだったら、当然コンパイルエラーを出してくれるものと勝手に期待していたのだけど、なぜかコンパイルを通り、ランタイムエラーで悩むハメに。

Objective-Cって型にわりと厳格な言語だと思っていたのだけど、案外そうでないのね。

「キャストくらいしろよ」的な警告くらいは出るかと思ってたのに驚きだ。

緩い調査課題

上のケースがコンパイルを通ってしまうというのは、ちょっと面白い現象だったので、時間があればどういう経緯があったのか調べてみようと思う。

まさか、UILabelがNSStringの継承オブジェクトということはないよね?

kaz_hiramatsukaz_hiramatsu2010/05/16 15:58stopUpdatingLocationのメッセージを出してもdidUpdateToLocationのメソッドが2回呼ばれる現象、自分も悩みました。
仕様なんですかね?
自分もこの前提で書きなおしました。

2010-03-02

Objective-Cにおけるenumとconstの差異が分からない

| 01:22

さほど重要ではないのだけど、定数を設定する時のObjective-Cの文法で少し疑問がある。

例えば、CLLocationAccuracyに設定する定数(kCLLocationAccuracyBest等の5つ)の定義を見ると、

  extern const CLLocationAccuracy kCLLocationAccuracyBest;
  extern const CLLocationAccuracy kCLLocationAccuracyNearestTenMeters;
  extern const CLLocationAccuracy kCLLocationAccuracyHundredMeters;
  extern const CLLocationAccuracy kCLLocationAccuracyKilometer;
  extern const CLLocationAccuracy kCLLocationAccuracyThreeKilometers;

となっている。

すでに記憶が定かでないのだが、はるか昔に使っていたC言語では定数を定義するときには、enumを使い

  enum hoge { FOO, BAR } hoge1;

と書いていた。*1

Objective-Cのドキュメントを見ても、文法的に誤りではないようだし、実際こう書いて期待通りに動作している。

だが、このenum、上のextern const〜を使った場合との違いは何だろう?

こちら(Cocoaのためのコーディングガイドライン)のページによれば、

浮動小数点値の定数を作成するにはconstを使用してください。また、他の定数に関連のない、整数の定数を作成するためにもconstを使用することができます。そうでない場合は、列挙型を使用してください。

とある。

  • const を使うケース
    1. 浮動小数点値の定数を作る
    2. 整数の定数を作る(他の定数に関連のない定数の場合)
  • enum を使うケース
    1. 整数の定数を作る(他の定数に関連のある定数の場合)

ということだろうか?

前述のCLLocationAccuracyに設定するkCLLocationAccuracyBestといった値は、わざわざ浮動小数点を使ってはいないだろうから、constの2)のケースのはずだ。

"他の定数に関連のある"というのは他の定数の定義で使われているといった意味ならば、今、自分のプログラムenumを使っている部分もconstの2)に該当しそうだ。(やっぱり、constを使った方が良いのかな?)

いずれ、時間に余裕が出たら調べてみることにする。

*1DOS時代のC言語にはconstって存在してなかったような気がする。記憶違い?

NaoNao2010/08/19 09:29constは定数を定義する。円周率など定数を定義するときに便利。
enumは連続した整数を定義する。赤は1、青は2・・という風に、何かを数字で区別したい時に便利。

ID2ndID2nd2010/08/20 01:14Naoさん、アドバイスありがとうございます。
じつは、私もまったく同じように思っており、連続した整数の定義に enum を利用しようとしていました。

ところが、Apple のコードでは enum の代わりに const が利用されています。(エントリ本文の extern const CLLocationAccuracy から始まる 5 行が Apple のコードです。)

言語として誤りということではないでしょうし、あくまで、Apple の COCOA 用に記述するときの推奨事項なのだろうと予想しています。(時間さえあれば、調べて解明したい…)

ashura156ashura1562010/12/10 18:55Cでの enum と const の違いは
const - 代入できない変数(≒殆どのケースでシンボル付きの定数だと考えてよい)である事を示す型修飾子
enum - 型を持つ整数定数群。

enum を使う事で得られるメリットは型を持てる事です。必ずしも連番として定義する必要はないです。

typedef enum {

}Color;

ashura156ashura1562010/12/10 19:01失礼、途中で投稿してしまいました。続きを
例えば下記の様に enum を受け取る関数を定義することで、引数として特定のenum型の定数を期待することを明示できます。

typedef enum{
RED, GREEN,
}Color;

void setColor(Color color);

残念ながら C 及び Objective-C では enum は型の扱いが緩いので上掲の関数に int値渡してもコンパイルは通ってしまいますが。
(若干話題から逸れますが C++ ではキャストしないと int値は渡せません)

ID2ndID2nd2010/12/11 03:55
丁寧で分かりやすい解説をありがとうございました。

少々細かい話になってしまいますが、実は今回エントリに書いた 「 extern const CLLocationAccuracy kCLLocationAccuracyBest (略)」の Apple が書いたコードを見ているときに思い出しのが、まさに例示いただいた

 typedef enum{
  RED, GREEN,
 } Color;

の記述法でした。これと同じ様に

 typedef enum {
  best精度, better精度, low精度
 }

と書くのが最も自然であるように私には思えたのがそもそもエントリを書くきっかけでした。
 
今考えるとそう考えた背景には、constを使う場合には

 const hoge 1;

と何らかのイミディエイトな値を指定するのが一般的だ。数値を指定しないで const を使うのは不自然だ」という思い込みがあったからかもしれません。

ID2ndID2nd2010/12/11 03:56本題の話とは全く関係ありませんが、このテーマに多くの人がコメント寄せてくださるのを、かなり嬉しく思ってます。

所詮「どう書いたっていいじゃない」といわれてしまえばそれまでの話題で、ひっかかるのは私くらいかと思ってましたから。

2010-02-27

おおむね完成?

| 04:15

とりあえず骨格部分だけは完成させた。

あとは実機を持って都内をうろうろ、テストして使い良い挙動に成るように煮詰めていくか。