最近、Apple の新しいコンパス フュージョン API を使用するように変換したアプリがあります。古い (現在は廃止された) API を使用していました。
これが、モーションの更新を有効にする方法です。位置情報サービスが利用できない場合は、システムが磁北から北を試すために磁気偏角を決定できないため、磁北を要求する必要があります。これを行わないと、コンパスがハングアップして何も起こりません
if ( [CLLocationManager headingAvailable] )
{
if ( [CLLocationManager locationServicesEnabled] )
[motionMgr startDeviceMotionUpdatesUsingReferenceFrame:CMAttitudeReferenceFrameXTrueNorthZVertical];
else
[motionMgr startDeviceMotionUpdatesUsingReferenceFrame:CMAttitudeReferenceFrameXMagneticNorthZVertical];
}
真北が取れないケースは他にもあると思います。デバイスを機内モードにすると、インターネットで偏角を検索できず、失敗します。システムが古い磁気偏角をキャッシュすることがあるため、この方法で失敗させるのは少し難しいです。
システムが真北に到達できるかどうかを判断するための好ましい方法を知っている人はいますか? Reachability クラスを使用することもできますが、それはやり過ぎかもしれません。キャッシュされた値により、真北を決定できる場合があります。
[編集]
これを行うには、やや堅牢な別の方法を見つけました。真北の方向を要求したときに真北を決定できない場合、要求時にモーション マネージャーの deviceMotion は nil になるようです。Motion Manager を起動して実行できるようにするには、起動してから 1 ~ 2 秒後にこれを行う必要があります。
[motionMgr startDeviceMotionUpdatesUsingReferenceFrame:CMAttitudeReferenceFrameXTrueNorthZVertical];
// Call checkForTrueNorth a second or so after starting motion updates to see if true north is available
// It needs a bit of time to get running. If it isn't available switch to using magnetic north.
[self performSelector:@selector(checkForTrueNorth) withObject:nil afterDelay:1.5];
- (void)checkForTrueNorth
{
if (motionMgr.deviceMotion == nil) // nil means it couldn't get true north.
{
[motionMgr stopDeviceMotionUpdates];
[motionMgr startDeviceMotionUpdatesUsingReferenceFrame:CMAttitudeReferenceFrameXMagneticNorthZVertical];
}
}
このメソッドに関する私の唯一の懸念は、この場合に nil が返されるという動作が文書化されていないと思うことです。現在は機能しますが、将来のリリースでは機能しない可能性があります。