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

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

新規登録して質問してみよう
ただいま回答率
85.48%
TableView

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

Swift

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

Q&A

解決済

1回答

358閲覧

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

otto-papa

総合スコア11

TableView

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

Swift

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

0グッド

0クリップ

投稿2017/12/08 13:31

問題:
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()
でどうしてテーブルビューに表示されないのか、どうすれば表示されるのかを教えてもらえないでしょうか?
よろしくお願いします。

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fromageblanc

2017/12/08 14:25

テーブル自体が表示されないのでしょうか?
otto-papa

2017/12/09 14:41

対応ありがとうございます。テーブル自体は表示されます。記述がお粗末で申し訳ありません。view自体はストーリーボードを使用して作成しています。UIViewControllerにユーティリティーエリアのtableViewをドラッグ&ドロップした単純なものです。connectedDeviceArrayに初期値["test1","test2","test3"]を設定しておくとtableViewCellに表示されます。また、DeviceManager.swiftとして別ファイルを作成せずに、TestViewController.swiftの中にまとめて記述してtableView.reloadData()を実行すると接続されてたデバイス名は表示されます。スレッドの問題かと思っているのですが如何でしょうか?protocolで渡しているデータがメインスレッドになっていないとか?
otto-papa

2017/12/10 01:31

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

2017/12/10 02:54

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

2017/12/10 13:02

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

回答1

0

自己解決

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

投稿2017/12/10 13:13

otto-papa

総合スコア11

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

otto-papa

2017/12/10 13:32

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問