首页 > 解决方案 > Swift UIButton:制作一个需要按三下的按钮

问题描述

我的问题:

是否可以将 UIButton 子类化为在实际调用该函数之前必须按三下按钮?

语境

我是一名裁判,所以在比赛中我需要记录剩余时间和两队的比分。因为我厌倦了同时使用纸和秒表,所以我决定制作一个应用程序来为我处理它。毕竟我是一名程序员,所以为什么不呢。

因为一直把手机拿在手里是不切实际的,所以我总是把手机(运行应用程序的手机)放在口袋里。我只在需要更改分数或发出哔哔声(表示时间到了)时才将其取出。为了防止我的手机在口袋里时意外按下其中一个按钮,我确保您必须连续按三次按钮以确保您确实打算按下它。我通过声明变量来跟踪我在屏幕上的每个按钮在最后一秒内按下了多少次来做到这一点。但这也意味着我必须拥有与屏幕上按钮数量一样多的变量,并且在调用函数时,我首先必须检查之前按下了多少次以确定是否执行代码。它有效,但我最终得到了一些非常混乱的代码。

标签: iosswiftuibutton

解决方案


如果你想避免混乱的代码,一种选择是从 UIKit 继承 UIButton 并实现@vacawama 提供的连续三次点击检测机制。

如果您想保持简单,并且只需要跟踪发生 3 次点击的最后一个按钮,那么您只需要一个与您正在计数的按钮关联的计数器以及最后一次点击它的时间。

一旦按键变化或时间间隔过长,跟踪按键变化,计数器返回 1。

当检测到在同一个按钮上连续三个轻击时,您会向原始目标触发事件并将计数器重置为 0。

import UIKit

class UIThreeTapButton : UIButton {

    private static var sender: UIThreeTapButton?
    private static var count = 0
    private static var lastTap = Date.distantPast

    private var action: Selector?
    private var target: Any?

    override func addTarget(_ target: Any?,
                            action: Selector,
                            for controlEvents: UIControl.Event) {
        if controlEvents == .touchUpInside {
            self.target = target
            self.action = action
            super.addTarget(self,
                            action: #selector(UIThreeTapButton.checkForThreeTaps),
                            for: controlEvents)
        } else {
            super.addTarget(target, action: action, for: controlEvents)
        }

    }

    @objc func checkForThreeTaps(_ sender: UIThreeTapButton, forEvent event: UIEvent) {
        let now = Date()
        if UIThreeTabButton.sender == sender &&
            now.timeIntervalSince(UIThreeTapButton.lastTap) < 0.5 {
            UIThreeTapButton.count += 1
            if UIThreeTapButton.count == 3 {
                _ = (target as? NSObject)?.perform(action, with: sender, with: event)
                UIThreeTapButton.count = 0
                UIThreeTapButton.lastTap = .distantPast
            }
        } else {
            UIThreeTapButton.sender = sender
            UIThreeTapButton.lastTap = now
            UIThreeTapButton.count = 1
        }
    }
}

推荐阅读