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

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

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

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

Q&A

解決済

2回答

2139閲覧

UILongPressGestureに設定したメソッドが何度も呼ばれてしまう

yoshiSwift

総合スコア34

Swift

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

0グッド

0クリップ

投稿2020/08/19 04:21

前提・実現したいこと

ボタンを長押しすると、UIAlertControllerが表示され、OKを押すと削除できる機能を目標としている。

該当のソースコード

//ボタンに長押しした時の処理を設定 let button = UIButton(type: .system) let longPressRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(deleteTag(_:))) button.addGestureRecognizer(longPressRecognizer) @objc func deleteTag(_ sender: UIButton) {      print(#function) let alert = UIAlertController(title: "削除しますか?", message: nil, preferredStyle: .alert) alert.addAction(.init(title: "OK", style: .default, handler: { (_) in //ボタン削除処理 (省略) })) alert.addAction(.init(title: "CANCEL", style: .cancel, handler: nil)) self.present(alert, animated: true, completion: nil) }

発生している問題・エラーメッセージ

deleteTag(_:) deleteTag(_:) deleteTag(_:) deleteTag(_:) ... 続く... //長押し後の処理が複数回呼ばれてしまうことで、「UIAlertControllerが表示されすぎです」という旨のエラーが出る。

試したこと

長押し後に、何度も処理が呼ばれず、一回だけ処理を行うことは可能でしょうか。
もしくは、どこかコードを間違えているのでしょうか。ご指摘お願いいたします。
以下を参考に、ボタンの長押し処理を作成しました。
https://otiai10.hatenablog.com/entry/2019/08/08/115240

補足情報(FW/ツールのバージョンなど)

xcode10.3

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

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

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

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

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

guest

回答2

0

自己解決

let longPressRecognizer = UILongPressGestureRecognizer() longPressRecognizer.addTarget(self, action: #selector(deleteTag(_:_:)))

ここまでは良かったのですが、#selectorの対象となる@objcの引数の書き方がよくなかったみたいです。
【悪い例】

@objc func deleteTag(_ sender: UIButton, _ gesture: UILongPressGestureRecognizer) { print(gesture.state.rawValue) }

【良い例】

@objc func deleteTag(_ sender: UILongPressGestureRecognizer, _ tag: UIButton) { print(sender.state.rawValue) }
@objc func deleteTag(_ sender: UILongPressGestureRecognizer, _ tag: UIButton)というように、引数の順序を変えたところ、state.valueの値が変化するようになりうまくいきました。

何度も処理が呼ばれるのは、UILongPressGestureRecognizerが、タッチされた瞬間、タッチされている間、タッチされ終わった(長押し終了)のタイミングを連続的に検知しているからでした。

追記
@objcの引数の順序(書き方)が問題となったエラーでしたが、@objc内で引数を使いたい時どちらの書き方でも引数を使えるような気がするのですが、今回のように実行結果に違いが出た理由はなんでしょうか。
@objcの引数の書き方にルールがあるのでしょうか、どなたか今回のエラーが出た根本的な理由を教えていただけるとありがたいです。

投稿2020/08/19 08:34

yoshiSwift

総合スコア34

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

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

guest

0

ジェスチャーリコグナイザが多数登録されているのではないでしょうか。

button.addGestureRecognizer(longPressRecognizer)

この部分は、どのメソッドに書いていますか?

投稿2020/08/19 07:18

eytyet

総合スコア803

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

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

yoshiSwift

2020/08/19 08:37

>ジェスチャーリコグナイザが多数登録されているのではないでしょうか。 viewDidLoad内で一回だけ登録してみましたが、結果は変わらず何度も呼ばれていました。 原因としては、私が引数の書き方を間違えていたせいで何度も無駄に処理が呼ばれていると勘違いしていたせいです。しっかりとコードを直した結果、タッチの開始、タッチされている間、タッチの終了を連続して検知していることが明らかになりました。 ご回答ありがとうございました。
eytyet

2020/08/19 11:29

解決したようで良かったです。惑わせてしまっていたらごめんなさい。 わざわざコメントを頂き、ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問