LoginSignup
38
34

More than 5 years have passed since last update.

BluetoothをもちいたiOS同士の通信

Posted at

概要

Bluetoothで通信をする1対1のゲームを作ろうと思い、テストとしてサンプルを作りました。その際に、以下の記事を参考にさせていただきました。
参考サイト
参考サイトではテキストのやり取りをしていますが、今回は数値のやり取りをすることに目標をおきました。また、タイトルには「Bluetooth」と書いてありますが、サンプルでは「Multipeer Connectivity」というライブラリを使用します。Multipeer Connectivityは、同じWi-Fiに接続されている端末同士でも通信できるので、Bluetoothをオンにしなくても通信することができるようです。(もちろんBluetoothでも通信できます)詳しい説明は割愛。

完成図

IMG_3409.PNG

作り方

1. 部品の配置

スクリーンショット 2017-04-15 17.27.03.png

ざっとこんなかんじに配置します。青と赤の枠はベタ塗りのラベルを後ろに置いてあるだけなので、特に意味はありません。

2. 部品の接続

次に、LabelとButtonをoutlet, Action接続していきます。

スクリーンショット 2017-04-15 18.40.35.png

それぞれの部品を接続すると、このようになると思います。

3. コードを書く

最後にコードを書いていきます。と言ってもほとんど参考サイトのコピペです。違うところは、自分の数値をNSData型へ変換して相手の端末に投げているところ。相手の端末から送られてきたNSDataをInt型へ変換して、ラベルを更新する関数へ投げているところです。

ViewController.swift
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にあげておきます。

38
34
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
38
34