今開発しているアプリで、Bluetoothを使用して、通信を行うものを入れようとしている。
この実装には、かなり苦労してしまったので、残す事にする。
Bluetoothは使った事が無かったので、いつも通りにネットで検索して、実装方法を参考にしていた。
まず始めに、「GameKit.framework」の「GKPeerPickerController」を使う事で実装した。
とりあえず動かしてみると、中途半端に動くので、調べてみると、「GKPeerPickerController」は、iOS7は未サポートであり、現在は、非推奨となっている。
これに変わるものとして、「MultipeerConnectivity.framework」が必要な、「MCBrowserViewController」「MCSession」を使用する方法になっていた。
これに関しても、ネットで検索すると、サンプルソースとともに、解説がいくつもあったので、分かりやすいと思うページを参考にするとよいと思う。
早速、これに置き換えようとして、解説を読んでいくと、新しい「MCBrowserViewController」は、iOS7からしか使用できないと書かれている。
仕方ないと思い、OSのバージョンを見て切り分けるように実装し、動作確認してみた。
すると、通信相手を検索にいくのだが、全く発見できない。
「GKPeerPickerController」をiOS7で使った時には、検索する事は出来ていたのに・・・
いろいろ試しながら、調べていくと、どうやら、「GKPeerPickerController」と「MCBrowserViewController」では、通信できないらしい。
これでは、はっきり言って使い物にならないのではないかと思ってしまう。
今回(いつも同じだが)、iOS6とiOS7の実機で確認するようにはしている。
特に今回は、2台で通信するので、それぞれ、別のOSの実機で確認していたから、すぐに気がついた。
一通り作り込んだ後に確認していたら、とんでもない後戻りになったと思う。
その点は、運がよかったのかも・・・
しかし、この事に関しては、あまり情報がなく、ほとんどが、それぞれの方法についての解説のみだった。
iOS6、iOS7の両方をサポートしたアプリを作ることは無理なのかとも思い始めていたが、やっと方法が見つかった。
iOS7の場合、「GKPeerPickerController」は、中途半端に動作するという事がポイント。
具体的には、接続状態が変更された時に呼ばれる「- (void)session:(id)session peer:(id)peerID didChangeState:(GKPeerConnectionState)state」が、切断された時にしか動かない。
この為、接続が確立した事が分からなくなってしまっているのだ。
そこで、対策として、接続処理が終わった時にコールされる「- (void)peerPickerController:(GKPeerPickerController *)picker didConnectPeer:(NSString *)peerID toSession:(GKSession *)session」で、iOS7の場合には、強制的に、「- (void)session:(id)session peer:(id)peerID didChangeState:(GKPeerConnectionState)state」をコールしてしまうと動かす事が出来た。
実際のソースは、下記のイメージ
- (void)peerPickerController:(GKPeerPickerController *)picker didConnectPeer:(NSString *)peerID toSession:(GKSession *)session
{
// セッションを保管
currentSession = session;
// デリゲートのセット
session.delegate = self;
// データ受信時のハンドラを設定
[session setDataReceiveHandler:self withContext:nil];
// ピアピッカーを閉じる
picker.delegate = nil;
[picker dismiss];
if (osVersion >= 7.0) {
// iOS7.0
if (self.isConnecting == NO)
[self session:currentSession peer:peerID didChangeState:GKPeerStateConnected];
}
}
- (void)session:(id)session peer:(id)peerID didChangeState:(GKPeerConnectionState)state
{
switch (state) {
case GKPeerStateAvailable:
// (省略)
break;
case GKPeerStateConnecting:
// (省略)
break;
case GKPeerStateConnected:
// 接続完了
self.isConnecting = YES;
// 接続完了後の処理をここに書く(省略)
break;
case GKPeerStateDisconnected:
// (省略)
break;
case GKPeerStateUnavailable:
// (省略)
break;
default:
break;
}
}
ポイントとなる「GKPeerStateConnected」の部分以外は基本的に省略しているが、上記のような実装で、うまく接続を確立して通信する事が出来た。
ただ、非推奨となっていて、iOS7では、未サポートとされるものを使用して、無理矢理動かした感が強いと思う。
そのため、どんな不具合が出るのか、今は予想できていない。
さらに、Appleの審査で問題とならないのかもよくわからない。
最悪の場合、iOS7専用にしてしまうと思うが、今の所は、このまま開発を進める。
(知り合いにも、iOS7が気に入らないからとアップデートしない人は、数人いるので、まだ、iOS6もサポートしたいと思う。)
最終的に、テスト、アプリ申請と進める上で、問題が出たら(問題なく完了しても)、ここに残す予定。
[3回]
PR