概要
- iPhoneでBluetooth通信を動かしてみたかったので、かんたんなサンプルを書いてみました
- 基本的に、
MultipeerConnectivity
で用意されている各クラスの初期化とデリゲートの実装だけ行えば、簡単にBluetooth通信ができました
つくったもの(Bluetooth通信のサンプル)
- 画面をタップすると、自分の端末に円がアニメーション表示されます
- Bluetooth通信で座標を送り、相手の端末にも同じ円が表示します
- 長押しで円がでかくなります
- スプラトゥーン風にしたかったのですが、だいぶコレジャナイ
サンプルコード
- BluetoothGameSample
- (エラー処理などいろいろ足りないです。とりあえずのサンプルになってます)
実行時の注意
- 端末のBluetooth設定をONにする必要があります(「設定」アプリ > Bluetooth > オン)
- アプリ起動すると、周囲に同じアプリが起動していないか探しに行きます(60秒タイムアウト)
- Bluetooth通信はシミュレータでは試せないようです
要点
0.使用したクラスについて
-
参考サイトにもあるように、
MCBrowserViewController
を使うと簡単に接続先の選択~接続の確立までをUI付きで提供してくれます。 - ただ、今回は接続先の 選択画面を挟みたくなかった ので、
MCBrowserViewController
の代わりにMCNearbyServiceBrowser
を使用し、最初に見つけた端末に即接続しに行っています
1.Bluetooth通信準備
- サンプルではちょっと処理を加えていますが、Bluetooth通信に最低限必要な初期化処理は以下のはず。
-
MCNearbyServiceAdvertiser
やMCNearbyServiceBrowser
の役割については、参考サイトの招待状の例えがわかりやすかったです
func initialize() {
self.peerID = MCPeerID(displayName: UIDevice.currentDevice().name)
self.session = MCSession(peer: peerID)
self.session.delegate = self
self.advertiser = MCNearbyServiceAdvertiser(peer: peerID, discoveryInfo: nil, serviceType: serviceType)
self.advertiser.delegate = self
self.advertiser.startAdvertisingPeer()
self.browser = MCNearbyServiceBrowser(peer: peerID, serviceType: serviceType)
self.browser.delegate = self
self.browser.startBrowsingForPeers()
}
// MARK: - MCNearbyServiceAdvertiserDelegate
func advertiser(advertiser: MCNearbyServiceAdvertiser, didReceiveInvitationFromPeer peerID: MCPeerID, withContext context: NSData?, invitationHandler: (Bool, MCSession) -> Void) {
invitationHandler(true, self.session);
}
// MARK: - MCNearbyServiceBrowserDelegate
func browser(browser: MCNearbyServiceBrowser, foundPeer peerID: MCPeerID, withDiscoveryInfo info: [String : String]?) {
self.browser.invitePeer(peerID, toSession: session, withContext: nil, timeout: 60)
}
2.データの送信
-
ViewController
のタッチイベントで、「相手端末への座標の送信」と「自分の座標への円の描画」を行っています - 以下はデータ送信部分
NearbyManager.swift
func sendMessage(point : PointModel) {
do {
let data = NSKeyedArchiver.archivedDataWithRootObject(point)
try self.session.sendData(data,
toPeers: self.session.connectedPeers,
withMode: MCSessionSendDataMode.Unreliable)
} catch {
print(error)
}
}
3.データの受信
- 受け取った座標データに従って、相手の円を描画しています
- 以下はデータ受信部分
NearbyManager.swift
// MARK: - MCSessionDelegate
func session(session: MCSession, didReceiveData data: NSData,
fromPeer peerID: MCPeerID) {
dispatch_async(dispatch_get_main_queue()) {
let point = NSKeyedUnarchiver.unarchiveObjectWithData(data) as! PointModel
self.canvasVC?.paintEnemyPuddle(point)
}
}
まとめと課題
-
MultipeerConnectivity
で用意されている各クラスのデリゲートを実装すれば、Bluetooth通信は簡単に実装できる - いろいろ考慮が足りていないので、実際に使うとなるといろいろ手を入れる必要がありそう
- この実装だと通信のタイムラグで2端末間の表示にズレが出ることがあるので、少なくともユーザのアクションの実行時間はデータとして持たせる必要がある
- エラー処理全般を入れていないので、相手が遠く離れた時やアプリを終了したときなど対応が必要
- 上記に関連するが、状況によってデータが相手に届かないことがある。ロストしたデータのフォローも必要