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

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

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

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

Swift 2

Swift 2は、Apple社が独自に開発を行っている言語「Swift」のアップグレード版です。iOSやOS X、さらにLinuxにも対応可能です。また、throws-catchベースのエラーハンドリングが追加されています。

Q&A

解決済

1回答

1611閲覧

multipeerconectivityを使ったアプリの動作が遅い

afuroda

総合スコア36

Swift

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

Swift 2

Swift 2は、Apple社が独自に開発を行っている言語「Swift」のアップグレード版です。iOSやOS X、さらにLinuxにも対応可能です。また、throws-catchベースのエラーハンドリングが追加されています。

0グッド

0クリップ

投稿2017/01/05 17:37

###前提・実現したいこと
swiftのmultipeerconectivityを使ってクイズアプリを作っているのですが、下記のコードでエラーも出ずに動くのですが、実機で試すと動作がものすごく遅く、didChangeStateのところのUIButtonの表示が画面を触らなければ表示されず、触ったところのUIだけ表示されたりしてしまいます。これは何か原因があるのでしょうか?

###該当のソースコード

swift

1class ViewController: UIViewController,MCSessionDelegate,MCNearbyServiceBrowserDelegate,MCNearbyServiceAdvertiserDelegate{ 2 3 //タグ 4 let BTN_ADV = 0 5 let BTN_BRW = 1 6 7 //各変数 8 let service = "p2p" 9 var button1 = UIButton() 10 var button2 = UIButton() 11 var peerID : MCPeerID? 12 var session : MCSession? 13 var browser : MCNearbyServiceBrowser? 14 var advertis : MCNearbyServiceAdvertiser? 15 16 var text = UILabel() 17 var button5 = UIButton() 18 var button6 = UIButton() 19 var button3 = UIButton() 20 var button4 = UIButton() 21 var answer : String? 22 var count = 0 23 24 25 26 27 override func viewDidLoad() { 28 29 //MCPeerIDの設定 30 peerID = MCPeerID(displayName: UIDevice.currentDevice().name) 31 32 //MCSessionの設定 33 session = MCSession(peer: peerID!) 34 session!.delegate = self 35 36 37 //MCNearbyServiceBrowser,MCNearbyServiceAdvertiserの設定 38 self.browser = MCNearbyServiceBrowser(peer: peerID!, serviceType: service) 39 self.browser!.delegate = self 40 self.advertis = MCNearbyServiceAdvertiser(peer: peerID!, discoveryInfo: nil, serviceType: service) 41 self.advertis?.delegate = self 42 43 //button1,button2の設定 44 button1.tag = BTN_BRW 45 button2.tag = BTN_ADV 46 button1.frame = CGRectMake(0, 0, 300, 100) 47 button2.frame = CGRectMake(0, 0, 300, 100) 48 button1.backgroundColor = UIColor.cyanColor() 49 button2.backgroundColor = UIColor.redColor() 50 button1.layer.position = CGPoint(x: self.view.frame.width/2, y: self.view.frame.width/1.2) 51 button2.layer.position = CGPoint(x: self.view.frame.width/2, y: self.view.frame.width/0.9) 52 self.view.addSubview(button1) 53 self.view.addSubview(button2) 54 button1.setTitle("browse", forState: .Normal) 55 button2.setTitle("advertis", forState: .Normal) 56 button1.addTarget(self, action: #selector(self.onclick(_:)), forControlEvents: .TouchUpInside) 57 button2.addTarget(self, action: #selector(self.onclick(_:)), forControlEvents: .TouchUpInside) 58 59 //クイズ画面のUI設定 60 text.frame = CGRectMake(0, 0, 300, 150) 61 button5.frame = CGRectMake(0, 0, 300, 100) 62 button6.frame = CGRectMake(0, 0, 300, 100) 63 button3.frame = CGRectMake(0, 0, 300, 100) 64 button4.frame = CGRectMake(0, 0, 300, 100) 65 66 //ボタンの位置を指定する 67 text.layer.position = CGPoint(x: self.view.frame.width/2, y: self.view.frame.width/4) 68 button5.layer.position = CGPoint(x: self.view.frame.width/2, y: self.view.frame.width/1.2) 69 button6.layer.position = CGPoint(x: self.view.frame.width/2, y: self.view.frame.width/0.9) 70 button3.layer.position = CGPoint(x: self.view.frame.width/2, y: self.view.frame.width/0.7) 71 button4.layer.position = CGPoint(x: self.view.frame.width/2, y: self.view.frame.width/0.6) 72 73 74 //ボタンにイベントを追加する 75 button5.addTarget(self, action: #selector(self.button1push), forControlEvents: .TouchUpInside) 76 button6.addTarget(self, action: #selector(self.button2push), forControlEvents: .TouchUpInside) 77 button3.addTarget(self, action: #selector(self.button3push), forControlEvents: .TouchUpInside) 78 button4.addTarget(self, action: #selector(self.button4push), forControlEvents: .TouchUpInside) 79 80 81 82 83 super.viewDidLoad() 84 // Do any additional setup after loading the view, typically from a nib. 85 } 86 87 //ブラウズとアドバタイズの関数 88 func onclick(sender: UIButton){ 89 if sender.tag == BTN_ADV{ 90 self.advertis!.startAdvertisingPeer() 91 _ = UIAlertController(title: "アドバタイズを開始しました", message: "招待しました", preferredStyle: .Alert) 92 } 93 else if sender.tag == BTN_BRW{ 94 self.browser!.startBrowsingForPeers() 95 } 96 } 97 98 99 //MCNearbyServiceBrowserのメソッド 100 func browser(browser: MCNearbyServiceBrowser, foundPeer peerID: MCPeerID, withDiscoveryInfo info: [String : String]?) { 101 print("[MCNearbyServiceBrowserDelegate] browser:foundPeer:withDiscoveryInfo:") 102 103 browser.invitePeer(peerID, toSession: self.session!, withContext: nil, timeout: 10) 104 } 105 106 func browser(browser: MCNearbyServiceBrowser, lostPeer peerID: MCPeerID) { 107 108 } 109 110 //MCNearbyServiceAdvertiserのメソッド 111 func advertiser(advertiser: MCNearbyServiceAdvertiser, didReceiveInvitationFromPeer peerID: MCPeerID, withContext context: NSData?, invitationHandler: (Bool, MCSession) -> Void) { 112 113 114 let alert = UIAlertController(title: "招待を受けました", message: "from \(peerID.displayName)", preferredStyle: .Alert) 115 alert.addAction(UIAlertAction(title: "参加", style: .Default) { action in 116 invitationHandler(true, self.session!) 117 }) 118 alert.addAction(UIAlertAction(title: "拒否", style: .Cancel) { action in 119 invitationHandler(false, self.session!) 120 }) 121 self.presentViewController(alert, animated: true, completion: nil) 122 } 123 124 125 //MCSessionのメソッド 126 func session(session: MCSession, peer peerID: MCPeerID, didChangeState state: MCSessionState) { 127 button1.removeFromSuperview() 128 button2.removeFromSuperview() 129 //ボタンを画面に表示させる 130 self.view.addSubview(text) 131 self.view.addSubview(button5) 132 self.view.addSubview(button6) 133 self.view.addSubview(button3) 134 self.view.addSubview(button4) 135 print("ボタン交換") 136 qizu1() 137 138 139 } 140 func session(session: MCSession, didReceiveData data: NSData, fromPeer peerID: MCPeerID) { 141 print("receivedData") 142 self.view.backgroundColor = UIColor.cyanColor() 143 self.qizu1() 144 145 } 146 147 func session(session: MCSession, didReceiveStream stream: NSInputStream, withName streamName: String, fromPeer peerID: MCPeerID) { 148 print("didReceiveStream") 149 } 150 151 func session(session: MCSession, didStartReceivingResourceWithName resourceName: String, fromPeer peerID: MCPeerID, withProgress progress: NSProgress) { 152 print("didStartReceivingResourceWithName") 153 } 154 155 func session(session: MCSession, didFinishReceivingResourceWithName resourceName: String, fromPeer peerID: MCPeerID, atURL localURL: NSURL, withError error: NSError?) { 156 print("didStartReceivingResourceWithName") 157 } 158 159 160 161 162 //各ボタンの不正解の判定 163 func button1push(sender: UIButton){ 164 165 if answer == "1"{ 166 self.view.backgroundColor = UIColor.redColor() 167 send(button5) 168 } 169 else { 170 self.view.backgroundColor = UIColor.blueColor() 171 } 172 } 173 func button2push(sender: UIButton){ 174 if answer == "2"{ 175 self.view.backgroundColor = UIColor.redColor() 176 send(button6) 177 178 } 179 else { 180 self.view.backgroundColor = UIColor.blueColor() 181 182 } 183 184 } 185 func button3push(sender: UIButton){ 186 if answer == "3"{ 187 self.view.backgroundColor = UIColor.redColor() 188 send(button3) 189 } 190 else { 191 self.view.backgroundColor = UIColor.blueColor() 192 193 } 194 195 } 196 func button4push(sender: UIButton){ 197 if answer == "4"{ 198 self.view.backgroundColor = UIColor.redColor() 199 send(button4) 200 201 } 202 else { 203 self.view.backgroundColor = UIColor.blueColor() 204 205 } 206 207 } 208 209 //正解だった場合のデータ送信 210 func send(sender: UIButton){ 211 let str = "text" 212 let data = (str as NSString).dataUsingEncoding(NSUTF8StringEncoding) 213 do{ 214 try self.session?.sendData(data!, toPeers: (self.session?.connectedPeers)!, withMode: .Reliable) 215 print("send data") 216 self.count += 1 217 self.qizu1() 218 if self.count == 5{ 219 220 } 221 }catch _ as NSError{ 222 print("sned error") 223 } 224 } 225 226 override func didReceiveMemoryWarning() { 227 super.didReceiveMemoryWarning() 228 // Dispose of any resources that can be recreated. 229} 230 231} 232

###補足情報(言語/FW/ツール等のバージョンなど)
xcode ver7.3.1 , swift2__イタリックテキスト__を使っています。

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

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

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

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

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

guest

回答1

0

ベストアンサー

まず、didChangeStateの中がメインスレッドかどうか調べます。

swift

1//MCSessionのメソッド 2func session(session: MCSession, peer peerID: MCPeerID, didChangeState state: MCSessionState) { 3 print(NSThread.isMainThread()) //※追加 4 :

falseが出力されたらメインスレッドではないということなので、UIに関する処理をメインスレッドで実行するようにします。

swift

1dispatch_sync(dispatch_get_main_queue()) { 2 button1.removeFromSuperview() 3 button2.removeFromSuperview() 4 //ボタンを画面に表示させる 5 self.view.addSubview(text) 6 self.view.addSubview(button5) 7 self.view.addSubview(button6) 8 self.view.addSubview(button3) 9 self.view.addSubview(button4) 10 print("ボタン交換") 11 qizu1() //※これは入れなくていいかも知れません 12}

ちょっと古い記事ですが、
UIKit とスレッドのお約束 / Fenrir Developer's Blog

投稿2017/01/05 23:42

編集2017/01/05 23:48
fuzzball

総合スコア16731

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

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

afuroda

2017/01/06 05:02

ありがとうございます。解決しました。 つけていただいた記事についてはUI部品は基本的にメインスレッドで処理するというイメージでよろしいのでしょうか?
fuzzball

2017/01/06 05:06

「基本的」ではなく、必ずメインスレッドで実行しないといけません。
fuzzball

2017/01/06 05:31

と、勢いで書いてしまいましたが、UIKit全体ということであれば「基本的に」で正しいです。 https://developer.apple.com/reference/uikit このドキュメントの冒頭に、 >> For the most part, use UIKit classes only from your app’s main thread. >> This is particularly true for classes derived from UIResponder >> or that involve manipulating your app’s user interface in any way. と書いてあります。 UIResponderを継承していたらダメ = UIViewを継承しているクラスは全部ダメということになります。(「必ず」と書いた理由はこれです)
afuroda

2017/01/10 06:59

ありがとうございます。 覚えておきます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問