質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

91.25%

  • Swift

    5311questions

    Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

  • TableView

    65questions

    TableView(UITableView)とは、リスト形式で表示するコントロールで、ほとんどのアプリに使用されています。画面を「行」に分けて管理し、一般的には各行をタップした際に詳細画面に移動します。

MultipeerConnectivityで接続完了したdisplay.nameをテーブルビューに表示したいのですが・・・

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 79

otto-papa

score 3

問題:
MultipeerConnectivityで接続可能になったデバイスを自動的に接続し、接続完了したデバイスのdisplay.nameを自前のテーブルビューに表示させたいのですが、接続が完了していても表示されません。

処理の流れ:
MCNearbyServiceAdvertiser、MCNearbyServiceBrowser、MCSessionはDeviceManagerという1つのswiftファイルにまとめてデバイスの管理をするようにして、接続が完了した時にtableViewのファイルにpeerIDを渡してtableView.reloadData()を実行するようにしています。

tableViewのファイル

import UIKit
import MultipeerConnectivity

class TestViewController: UIViewController, UITableViewDataSource, UITableViewDelegate{

    let deviceManager = DeviceManager()
    let tableView = UITableView()
    @IBOutlet weak var label: UILabel!
    var connectedDeviceArray: [String] = []
    override func viewDidLoad() {
        super.viewDidLoad()
        deviceManager.delegate = self
        tableView.dataSource = self
        tableView.delegate = self
    }

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "backTapped"{
            connectedDeviceArray = []
        }
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
        cell.textLabel?.text = connectedDeviceArray[indexPath.row]
        cell.textLabel?.numberOfLines = 2
        return cell
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // #warning Incomplete implementation, return the number of sections
        print("connectedDeviceArray.count = \(self.connectedDeviceArray.count)")
        return connectedDeviceArray.count
    }

    func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        return "接続デバイス"
    }

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

    }
}

extension TestViewController: DeviceManagerDelegate{
    func connectedDevices(manager : DeviceManager, peerID: MCPeerID){
        OperationQueue.main.addOperation {
            self.connectedDeviceArray.append(peerID.displayName)
            print("connectedDeviceArray = \(self.connectedDeviceArray)")      //print文
            self.tableView.reloadData()
        }
    }
}


DeviceManagerファイル

import UIKit
import MultipeerConnectivity

protocol DeviceManagerDelegate{
    func connectedDevices(manager: DeviceManager, peerID: MCPeerID)
}

class DeviceManager: NSObject {

    private let serviceType = "hogefuga"
    private let peerID = MCPeerID(displayName: UIDevice.current.name)
    private let serviceAdvertiser : MCNearbyServiceAdvertiser
    private let serviceBrowser : MCNearbyServiceBrowser

    var delegate : DeviceManagerDelegate?

    override init() {
        self.serviceAdvertiser = MCNearbyServiceAdvertiser(peer: peerID, discoveryInfo: nil, serviceType: serviceType)
        self.serviceBrowser = MCNearbyServiceBrowser(peer: peerID, serviceType: serviceType)
        super.init()
        self.serviceAdvertiser.delegate = self
        self.serviceAdvertiser.startAdvertisingPeer()

        self.serviceBrowser.delegate = self
        self.serviceBrowser.startBrowsingForPeers()
    }

    deinit {
        self.serviceAdvertiser.stopAdvertisingPeer()
        self.serviceBrowser.stopBrowsingForPeers()
    }

    lazy var session : MCSession = {
        let session = MCSession(peer: self.peerID, securityIdentity: nil, encryptionPreference: .required)
        session.delegate = self
        return session
    }()
}

extension DeviceManager: MCNearbyServiceAdvertiserDelegate{

    func advertiser(_ advertiser: MCNearbyServiceAdvertiser, didReceiveInvitationFromPeer peerID: MCPeerID, withContext context: Data?, invitationHandler: @escaping (Bool, MCSession?) -> Void) {
        print("%@", "didReceiveInvitationFromPeer \(peerID)")
        invitationHandler(true, self.session)
    }

    func advertiser(_ advertiser: MCNearbyServiceAdvertiser, didNotStartAdvertisingPeer error: Error) {

    }
}

extension DeviceManager: MCNearbyServiceBrowserDelegate{

    func browser(_ browser: MCNearbyServiceBrowser, foundPeer peerID: MCPeerID, withDiscoveryInfo info: [String : String]?) {
        browser.invitePeer(peerID, to: self.session, withContext: nil, timeout: 10)
    }

    func browser(_ browser: MCNearbyServiceBrowser, didNotStartBrowsingForPeers error: Error) {
        print("%@", "didNotStartBrowsingForPeers: \(error)")
    }

    func browser(_ browser: MCNearbyServiceBrowser, lostPeer peerID: MCPeerID) {
        print("\(peerID.displayName)の接続が切れました。")
    }
}

extension DeviceManager: MCSessionDelegate{

    func session(_ session: MCSession, peer peerID: MCPeerID, didChange state: MCSessionState) {
        switch state {
        case .notConnected:
            print("セッションが未接続状態になりました。DisplayName = \(peerID.displayName)")
        case .connected:
            print("セッションは接続状態になりました。DisplayName = \(peerID.displayName)")
            self.delegate?.connectedDevices(manager: self, peerID: peerID)
        default:
            print("セッションは接続中です。DisplayName = \(peerID.displayName)")
        }
    }

    func session(_ session: MCSession, didReceive data: Data, fromPeer peerID: MCPeerID) {

    }

    func session(_ session: MCSession, didReceive stream: InputStream, withName streamName: String, fromPeer peerID: MCPeerID) {

    }

    func session(_ session: MCSession, didStartReceivingResourceWithName resourceName: String, fromPeer peerID: MCPeerID, with progress: Progress) {

    }

    func session(_ session: MCSession, didFinishReceivingResourceWithName resourceName: String, fromPeer peerID: MCPeerID, at localURL: URL?, withError error: Error?) {

    }
}

tableViewのファイルのprint文(//print文の部分)ではconnectedDeviceArrayの中がログに表示されるのですが、次のステップのself.tableView.reloadData()
でどうしてテーブルビューに表示されないのか、どうすれば表示されるのかを教えてもらえないでしょうか?
よろしくお願いします。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • otto-papa

    2017/12/10 10:31

    やはり、protocolへのデータの受け渡しのself.delegate?.connectedDevices(manager: self, peerID: peerID)がメインスレッドではなかったのでOperationQueue.main.addOperation{self.delegate?.connectedDevices(manager: self, peerID: peerID)}にて実行しましたが、tableViewには表示されず行き詰まっています。

    キャンセル

  • fromageblanc

    2017/12/10 11:54

    アウトレット接続してるということですと、let tableView = UITableView() のコードが気になります。ただ、ファイルを分けなければ正常な稼働をするならスコープの問題なのかも。Swift4でprivateとfileprivateの挙動が若干変更されています。

    キャンセル

  • otto-papa

    2017/12/10 22:02

    fromageblancさんありがとうございます。"let tableView = UITableView() のコードが気になります。"で気づきました。ケアレスミスでoutlet接続になっていませんでした。スコープもprivateからfileprivateに修正することできちんと表示されるようになりました。貴重なお時間を割いて頂き感謝します。

    キャンセル

回答 1

check解決した方法

0

製作中アプリの仕様変更で、テーブルビューをコード記述からストーリーボードでの製作に変更した際の単純なoutlet接続忘れでした。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/12/10 22:32

    fromageblancさん貴重な時間を割いて頂きありがとうございました。スコープについても従来のprivateではextensionで参照できないこと見落としていて勉強になりました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

ただいまの回答率

91.25%

関連した質問

同じタグがついた質問を見る

  • Swift

    5311questions

    Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

  • TableView

    65questions

    TableView(UITableView)とは、リスト形式で表示するコントロールで、ほとんどのアプリに使用されています。画面を「行」に分けて管理し、一般的には各行をタップした際に詳細画面に移動します。