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

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

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

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

Q&A

解決済

3回答

3405閲覧

[swift3]touchesEndedが呼び込まれずに暴走してしまう

yohuchan

総合スコア11

Swift

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

0グッド

0クリップ

投稿2016/12/18 14:16

編集2016/12/18 14:54

上下左右のコントロールボタンで座標を動かすプログラムを作っているのですが、ボタンを長押し(3秒ぐらいの時もあるし15〜20秒ぐらいの時もあります)して放すとtouchesEndedが呼び込まれないバグが時々出て暴走してしまいます。この原因がわかりません。

import

1import GameplayKit 2class GameScene: SKScene { 3 //コントローラー 4 let upButton = SKLabelNode(fontNamed: "Avenir-Black") 5 let downButton = SKLabelNode(fontNamed: "Avenir-Black") 6 let leftButton = SKLabelNode(fontNamed: "Avenir-Black") 7 let rightButton = SKLabelNode(fontNamed: "Avenir-Black") 8 //BOXラベル 9 var boxaddress: [SKLabelNode] = [] 10 var dx:[Int] = [] 11 var dy:[Int] = [] 12 //コントローラースイッチ 13 var isTouchedUp = false 14 var isTouchedDown = false 15 var isTouchedLeft = false 16 var isTouchedRight = false 17 //スイッチ内容ラベル 18 let SWLabel = SKLabelNode(fontNamed: "Avenir-Black") 19 var SW:[SKLabelNode] = [] 20 21 override func didMove(to view: SKView) { 22 23 //コントローラー表示 24 upButton.text = "UP" 25 upButton.fontSize = 30 26 upButton.position = CGPoint(x:375,y:150) 27 downButton.text = "DOWN" 28 downButton.fontSize = 30 29 downButton.position = CGPoint(x:375,y:50) 30 leftButton.text = "LEFT" 31 leftButton.fontSize = 30 32 leftButton.position = CGPoint(x:200,y:100) 33 rightButton.text = "RIGHT" 34 rightButton.fontSize = 30 35 rightButton.position = CGPoint(x:600,y:100) 36 self.addChild(upButton) 37 self.addChild(downButton) 38 self.addChild(leftButton) 39 self.addChild(rightButton) 40 //BOXラベル表示 41 for i in 0...5{ 42 for f in 0...5{ 43 let boxLabel = SKLabelNode(fontNamed: "Avenir-Black") 44 boxLabel.fontSize = 30 45 boxLabel.fontColor = SKColor.red 46 boxLabel.position = CGPoint(x:-200 + 300 * i,y:200 + 100 * f) 47 boxLabel.text = "X:\(Int(boxLabel.position.x)),Y:\(Int(boxLabel.position.y))" 48 dx.append(Int(boxLabel.position.x)) 49 dy.append(Int(boxLabel.position.y)) 50 boxaddress.append(boxLabel) 51 self.addChild(boxLabel) 52 }//for 53 }//for 54 }//did 55 56 override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { 57 for touch: AnyObject in touches { 58 let location = touch.location(in: self) 59 let touchNode = self.atPoint(location) 60 if touchNode == upButton { 61 isTouchedUp = true 62 } else if touchNode == downButton { 63 isTouchedDown = true 64 } else if touchNode == leftButton { 65 isTouchedLeft = true 66 } else if touchNode == rightButton { 67 isTouchedRight = true 68 } 69 }//for touch 70 }//touchesBegan 71 72 override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) { 73 for touch: AnyObject in touches { 74 let location = touch.location(in: self) 75 let touchNode = self.atPoint(location) 76 if touchNode == upButton { 77 isTouchedUp = false 78 } else if touchNode == downButton { 79 isTouchedDown = false 80 } else if touchNode == leftButton { 81 isTouchedLeft = false 82 } else if touchNode == rightButton { 83 isTouchedRight = false 84 } 85 86 }//for 87 }//touchesEnded 88 89 override func update(_ currentTime: TimeInterval) { 90 for i in 0...35{ 91 if isTouchedUp { 92 dy[i] -= 5 93 boxaddress[i].text = "X:\(dx[i]),Y:\(dy[i])" 94 } 95 if isTouchedDown { 96 dy[i] += 5 97 boxaddress[i].text = "X:\(dx[i]),Y:\(dy[i])" 98 } 99 if isTouchedLeft { 100 dx[i] += 5 101 boxaddress[i].text = "X:\(dx[i]),Y:\(dy[i])" 102 } 103 if isTouchedRight { 104 dx[i] -= 5 105 boxaddress[i].text = "X:\(dx[i]),Y:\(dy[i])" 106 } 107 }//for 108 }//update 109 110}//class 111コード

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

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

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

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

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

guest

回答3

0

押しっぱなしになる原因は長押しではありません。
ボタンを押したまま指をスライドさせて、ボタンの外で指を離すと暴走します。
touchesEnded自体は呼ばれていますが、その中のif文に引っ掛からないためです。

ボタンの仕様(同時押し、スライド時の挙動など)が分からないので修正方法は書きません。(というか書けません)
touchesMoved()は実装しないとダメでしょうね。

投稿2016/12/21 01:25

fuzzball

総合スコア16731

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

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

0

自己解決

この事象はAと言う行為をすると必ずこのエラーが出るというものではなく、
継続してBとかCとかDとか、というアクションを行うと高い確率でエラーが出るという事例でして、実際にこのコードを実行していただけないと
体感的にわからないだろと思ってコード全体をポストさせって頂いたもので、丸投げと思われ、不快に思われた方々にはお詫びを申し上げます。

さて、本題に入らせていただきますが、完全な解決には至っておりませんが、
自分なりに焦点を絞ってみました。
(1)update関数
(2)touchesBegan
(3)touchesEnded
この3個の問題の関連性を推測の範囲内で考察してみました。

まず、暴走が始まった時(touchesEndedが呼び込まれなくなった時:この方向を仮に上としましょう)に、
他の方向(左・右・下のいずれか)のボタンをタッチすると(touchesBegan)は呼び込まれます。
そして、指を離すと現在タッチしていたボタンは"touchesEnded"を呼び出し停止します。
しかし、暴走した方向のスイッチは切れません。
この段階でtouchesBegan or touchesEndedのどちらの問題なのかと考えると。。
touchesEndedになにかしら問題があるように感じました。
何故なら、暴走中にもtouchesBeganは反応しているからです。

update関数は1秒間に60回前後のルーティンを行っているようなのでtouchesEndedがこの処理についてこれていないと考えられます。(touchesEndedの脆弱性なのでしょうか?)そこで、もっと簡素な命令に変えてみました。(下記コード)

swift3

1コード 2 override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) { 3 isTouchedUp = false 4 isTouchedDown = false 5 isTouchedLeft = false 6 isTouchedRight = false 7}

以上のように全ての方向への許可を許さないと、今のところ暴走は起きておりません。
推測だと、touchesBeganはある程度細かい命令もこなしますが、
touchesEndedは細かい命令にはついてこれないようです。

これが正解とは絶対に言えませんが、今のところ理にかなった考え方のように思えます。
これでも、問題が発生した場合は、プログラム上でダブルブレーキ的な物を作る必要があります。
しかし、問題の本質からは離れていくように思われますね。
もっと完璧なプログラムがあるに違いないと思うのですが、今のところ考えつきません。

投稿2016/12/19 14:48

編集2016/12/19 14:50
yohuchan

総合スコア11

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

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

0

推測ですが、touchesCancelledも実装してみましょう。

投稿2016/12/19 03:58

pebble8888

総合スコア390

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

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

yohuchan

2016/12/19 14:44

アドバイスありがとうございます。しかしながら、同じような振る舞いをしてしまいます。 update関数とtouchesEndedの関係で問題があるような気がします。(あくまでも、推測ですが。)
pebble8888

2016/12/20 13:16

結論から言うと、質問者さんのプログラムにはバグがあります。 1) touchedEnded内のコードを全て削除し、 ``` isTouchedUp = false isTouchedDown = false isTouchedLeft = false isTouchedRight = false ``` を入れると質問者さんが暴走と呼んでいる現象は起きなくなるでしょう。 2) ついでに言うと、isTouchedUp,isTouchedDown,isTouchedLeft,isTouchedRightのように4つの変数を用いるべきではありません。 4つのボタンが同時に認識されることはないと考えると、 一つの変数で4種類の値を持つようにするべきでしょう。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問