LoginSignup
56
52

More than 5 years have passed since last update.

UIButtonなどの同時タップを禁止する再帰メソッド

Last updated at Posted at 2015-02-09

前置き

UIButtonなどの同時タップにより起きる不具合は多い。

例えば、UINavigationControllerなどを使っている画面で、pushするボタンを同時タップすれば同時に2つのViewControllerがpushされ、意図した画面階層にならなくなる。

(私はこれを”ViewController階層が破壊された”と表現している)

同時タップを禁止する

それを防ぐには簡単で、UIViewで定義されているexclusiveTouchをtrueにしてあげれば良い。

button1.exclusiveTouch = true
button2.exclusiveTouch = true

これでbutton1button2の同時タップは禁止される。

再帰的に適用する

こんな感じで簡単にできるものなのだが、いかんせん 面倒な上に設定漏れがあったらアウト である。

そもそも 同時タップを有効にしたい方が稀 なので、デフォルトですべての同時タップを禁止したいくらいである。

というわけで以下のように再帰的に適用するコードを書くと便利な気がした。

import UIKit

extension UIViewController {

    func exclusiveAllTouches() {
        self.exclusiveTouches(self.view)
    }

    private func exclusiveTouches(view: UIView) { // 再帰関数
        for view in view.subviews {
            let aView = view as UIView
            aView.exclusiveTouch = true
            self.exclusiveTouches(aView)
        }
    }
}

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        self.exclusiveAllTouches() // これを呼ぶだけで同時タップが防げる

        // TODO: 同時タップを許したいViewだけ個別にexclusiveTouchをfalseに
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}

おまけ

Swift使いだったら以下のように書くのがスマート(たぶん)

extension UIViewController {

    func exclusiveAllTouches() {
        self.applyAllViews { $0.exclusiveTouch = true }
    }

    func applyAllViews(apply: (UIView) -> ()) {
        apply(self.view)
        self.applyAllSubviews(self.view, apply: apply)
    }

    private func applyAllSubviews(view: UIView, apply: (UIView) -> ()) {
        let subviews = view.subviews as [UIView]
        subviews.map { (view: UIView) -> () in // Swiftのmapって戻り値なくても大丈夫なのね(ちょっと不気味
            apply(view)
            self.applyAllSubviews(view, apply: apply)
        }
    }
}
56
52
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
56
52