概要
Bluetoothで通信をする1対1のゲームを作ろうと思い、テストとしてサンプルを作りました。その際に、以下の記事を参考にさせていただきました。
参考サイト
参考サイトではテキストのやり取りをしていますが、今回は数値のやり取りをすることに目標をおきました。また、タイトルには**「Bluetooth」と書いてありますが、サンプルでは「Multipeer Connectivity」**というライブラリを使用します。Multipeer Connectivityは、同じWi-Fiに接続されている端末同士でも通信できるので、Bluetoothをオンにしなくても通信することができるようです。(もちろんBluetoothでも通信できます)詳しい説明は割愛。
完成図
#作り方
##1. 部品の配置
ざっとこんなかんじに配置します。青と赤の枠はベタ塗りのラベルを後ろに置いてあるだけなので、特に意味はありません。
##2. 部品の接続
次に、LabelとButtonをoutlet, Action接続していきます。
それぞれの部品を接続すると、このようになると思います。
##3. コードを書く
最後にコードを書いていきます。と言ってもほとんど参考サイトのコピペです。違うところは、自分の数値をNSData型へ変換して相手の端末に投げているところ。相手の端末から送られてきたNSDataをInt型へ変換して、ラベルを更新する関数へ投げているところです。
import UIKit
import MultipeerConnectivity
class ViewController: UIViewController, MCBrowserViewControllerDelegate,
MCSessionDelegate, UITextFieldDelegate {
let serviceType = "LCOC-Chat"
var browser : MCBrowserViewController!
var assistant : MCAdvertiserAssistant!
var session : MCSession!
var peerID: MCPeerID!
var p1num : Int = 0
@IBOutlet weak var player1Label: UILabel!
@IBOutlet weak var player2Label: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
self.peerID = MCPeerID(displayName: UIDevice.current.name)
self.session = MCSession(peer: peerID)
self.session.delegate = self
// create the browser viewcontroller with a unique service name
self.browser = MCBrowserViewController(serviceType:serviceType,
session:self.session)
self.browser.delegate = self;
self.assistant = MCAdvertiserAssistant(serviceType:serviceType,
discoveryInfo:nil, session:self.session)
// tell the assistant to start advertising our fabulous chat
self.assistant.start()
}
// プラスボタン
@IBAction func plusBtn(_ sender: Any) {
// プラス
p1num += 1
// NSDataへInt型のp1numを変換
let data = NSData(bytes: &p1num, length: MemoryLayout<NSInteger>.size)
// 相手へ送信
do {
try self.session.send(data as Data, toPeers: self.session.connectedPeers, with: MCSessionSendDataMode.unreliable)
} catch {
print(error)
}
player1Label.text = String(p1num)
}
// マイナスボタン
@IBAction func minusBtn(_ sender: Any) {
p1num -= 1
let data = NSData(bytes: &p1num, length: MemoryLayout<NSInteger>.size)
do {
try self.session.send(data as Data, toPeers: self.session.connectedPeers, with: MCSessionSendDataMode.unreliable)
} catch {
print(error)
}
player1Label.text = String(p1num)
}
// ラベルの更新
func updateLabel(num : Int, fromPeer peerID: MCPeerID) {
// peerが自分のものでない時ラベルの更新
switch peerID {
case self.peerID:
break
default:
player2Label.text = String(num)
}
}
@IBAction func showBrowser(sender: UIButton) {
// Show the browser view controller
self.present(self.browser, animated: true, completion: nil)
}
func browserViewControllerDidFinish(
_ browserViewController: MCBrowserViewController) {
// Called when the browser view controller is dismissed (ie the Done
// button was tapped)
self.dismiss(animated: true, completion: nil)
}
func browserViewControllerWasCancelled(
_ browserViewController: MCBrowserViewController) {
// Called when the browser view controller is cancelled
self.dismiss(animated: true, completion: nil)
}
// 相手からNSDataが送られてきたとき
func session(_ session: MCSession, didReceive data: Data,
fromPeer peerID: MCPeerID) {
DispatchQueue.main.async() {
let data = NSData(data: data)
var player2num : NSInteger = 0
data.getBytes(&player2num, length: data.length)
// ラベルの更新
self.updateLabel(num: player2num, fromPeer: peerID)
}
}
// The following methods do nothing, but the MCSessionDelegate protocol
// requires that we implement them.
func session(_ session: MCSession,
didStartReceivingResourceWithName resourceName: String,
fromPeer peerID: MCPeerID, with progress: Progress) {
// Called when a peer starts sending a file to us
}
func session(_ session: MCSession,
didFinishReceivingResourceWithName resourceName: String,
fromPeer peerID: MCPeerID,
at localURL: URL, withError error: Error?) {
// Called when a file has finished transferring from another peer
}
func session(_ session: MCSession, didReceive stream: InputStream,
withName streamName: String, fromPeer peerID: MCPeerID) {
// Called when a peer establishes a stream with us
}
func session(_ session: MCSession, peer peerID: MCPeerID,
didChange state: MCSessionState) {
// Called when a connected peer changes state (for example, goes offline)
}
}
#使い方
- 実行して「Browser」ボタンを押すと、接続可能な端末が表示される
- 任意の端末を選択すると、相手の端末に接続の許可を求めるアラートが出てくるので、「Accept」ボタンを押す
- 接続が完了したら、「Done」ボタンを押して元の画面に戻る
- 「+」ボタン「-」ボタンを押すと、相手側でも数値の変化が見られる
#まとめ
BluetoothをもちいてiOS端末同士で通信をしました。端末同士がやり取りするデータはNSDataなので、他にもいろいろなデータをやり取りすることができるようです。
注意点は、デバックには実機を使わないといけないところです。つまり今回のサンプルを動かすには、iPhoneが2台必要です。
今回作ったプロジェクトをGithubにあげておきます。