iBeacon開発ハマリどころポイントまとめ

```
# 【ご注意ください】
この記事を書いた後にiBeacon周りの仕様は大きく変更しています。
そのため下記の情報は古い可能性がありますのでご注意ください
```
  


[＠himara2](https://twitter.com/himara2) です。[iBeacon Advent Calendar](http://qiita.com/advent-calendar/2013/ibeacon) の4日目を担当させて頂きます。
ここまで概要や作品の紹介が多いようですので、私は開発時の注意点を書きます。

# 背景

以前「5分でわかるiBeacon」というスライドを公開させて頂きました。

* [5分でわかるiBeacon | SlideShare](http://www.slideshare.net/himaratsu/potatotips-ibeacon)
<a href="http://b.hatena.ne.jp/entry/http://www.slideshare.net/himaratsu/potatotips-ibeacon"><img src="http://b.hatena.ne.jp/entry/image/http://www.slideshare.net/himaratsu/potatotips-ibeacon"></a>

iOSデバイス2台で開発していたのですが、BLEに不慣れなこともありいくつかハマりました。
この記事ではこれからiBeacon開発を始める人向けに「開発時のハマリどころポイント」をまとめたいと思います。
  
※なお、前提として上記のスライドで簡単にまとめた実装方法は理解している想定で進めます。

# iBeacon開発ハマリどころポイント

## 1. バックグラウンド処理の注意点

### Background Mode にチェック入れる

Xcodeのプロジェクトの設定を変更しないとバックグラウンド処理が行えないので注意。
CoreLocationのdelegate methodがバックグラウンドで呼ばれない時にチェック。
![Xcode-Setting](http://f.cl.ly/items/0u1T2w1n3r0E3A0k2S0W/xcode_setting.png)

### デバイス設定でバックグラウンド処理を許可する

iOS 7からはデバイス設定でバックグラウンド処理が許可されていないとLocation Servicesを使えません。
以下の手順で設定します。
![Background-Setting](http://f.cl.ly/items/1f142D0O3d1H3z2t1W3S/bg_setting.png)

### AppSwitcherでプロセスを落とした場合は呼ばれない

iOS 7からAppSwitcher（ホームボタンダブルタップ画面で現れる画面）が導入されました。このAppSwitcherで上スワイプでプロセスを消すとバックグラウンド処理ができなくなります。
![AppSwitcher](http://f.cl.ly/items/1l0H3u3p3B31293F0F0u/appswitcher.png)

## 2. 実装時の注意点

### CoreBluetoothは使わなくてOK

iBeaconの受信/発信ではCoreBluetoothはimportしなくてOKです。  
CoreLocationフレームワークが必要に応じて適宜呼び出してくれているようです。

### リージョン監視 → レージングの順で呼ぶ

iBeaconでは、以下の2つを組み合わせて位置近接を測定します。

* エリアへの出入りを監視する「リージョン監視」
* エリア内でのビーコン情報を取得する「レージング」

それぞれの検知には順序があり、必ず 「リージョン監視」→「レージング」の順に呼ぶ必要があります。
同時に読んだりすると不具合が発生する可能性がありますので注意しましょう。

なお、それぞれの検知を開始/停止するメソッドは以下の通りです：

* リージョン監視
    * 開始： `- (void)startMonitoringForRegion:(CLRegion *)region;`
    * 停止： `- (void)stopMonitoringForRegion:(CLRegion *)region;`
* レージングの開始
    * 開始：`- (void)startRangingBeaconsInRegion:(CLBeaconRegion *)region;`
    * 停止：`- (void)stopRangingBeaconsInRegion:(CLBeaconRegion *)region;`


### 受信側アプリで登録できるUUIDはMAX20件まで

受信側のアプリではUUIDを指定して監視のターゲットに登録します。  
登録の上限は20件のようで、それを超えた場合はエラーとなり以下のメソッドが呼ばれます。

```objc
- (void)locationManager:(CLLocationManager *)manager monitoringDidFailForRegion:(CLRegion *)region withError:(NSError *)error
{
    // error.codeには kCLErrorRegionMonitoringFailure が入っている
}
```

## 3. デバッグ時の注意点

### [誤]アプリ起動直後からレージングエリアだと感知しない

**12/4 13:12 編集**
コメント欄で@chun_ryoさんよりご指摘頂きました。
レージングのエリア内でアプリを起動した場合でもビーコン感知は可能なようです。

詳細は下記のブログをご参考下さい：

* [iBeacon Tips: 正しいビーコン監視方法](http://brightechno.com/blog/archives/220)

`requestStateForRegion:`, `didDetermineState` を使って現在のステータスを取得できるようです。


### 境界問題について

上述の通り「出入り」を感知するのですが、を感知できる境界付近をうろうろした時、出たり入ったりを毎回感知してはユーザーに情報を与えすぎてしまいます。  
これを防ぐためにOS側が境界付近の管理を行っています。デバッグ時に領域への出入りを繰り返して反応がない場合は疑ってみましょう。

### 正確な距離はとれない

ビーコンからとれる情報は`CLBeacon`クラスに格納されますが、正確な距離を測ることはできません。
rssi（電波強度）はとれるので、これをベースにおおよその距離を算出することはできます。ただし周囲の環境によってrssiの値は上下します。
Appleのドキュメントにも正確な距離の測定用途ではないという話が書いてあるので、あくまで"おおよその位置"の検出に使うのが良さそうです。

### ビーコン側はバックグラウンド処理できない

受信側のアプリはバックグラウンドで処理を受けることができますが、送信側アプリはできません。  


# 今後もまとめていきます!

他にもハマりポイントがあれば随時追記していきますので、
コメント欄や[＠himara2](https://twitter.com/himara2)まで教えてください。  

この記事がこれから開発を始めるみなさんにとっての転ばぬ先の杖になることを願っています！