You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

iOS Swift:UILongPressGestureRecognizer同时启用数量受限问题求助

解决iOS合成器多触摸手势识别限制问题

问题根源

你遇到的核心问题并非硬件触摸点数限制(iOS设备普遍支持至少10点同时触摸),而是UILongPressGestureRecognizer在设置minimumPressDuration=0时的内部机制冲突,以及手势识别器默认的并发识别限制导致:

  • 用长按手势模拟即时触摸时,手势识别器的事件分发逻辑在超过5个并发时会出现阻塞,无法识别后续触摸
  • 手势状态未正确响应手指抬起事件,导致前5个手势一直保持激活状态

解决方案

方案1:放弃手势识别器,直接重写触摸事件(推荐)

使用UIView原生的触摸方法替代手势识别器,直接处理按下/抬起事件,完全避开手势识别的并发限制:

创建自定义按钮类:

class SynthButton: UIView {
    // 关联对应振荡器实例
    var oscillator: AKOscillator?

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesBegan(touches, with: event)
        // 启动振荡器
        oscillator?.start()
        // 模拟颜色变化逻辑
        backgroundColor = .systemRed
    }

    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesEnded(touches, with: event)
        stopPlayback()
    }

    override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesCancelled(touches, with: event)
        stopPlayback()
    }

    private func stopPlayback() {
        oscillator?.stop()
        backgroundColor = .systemGray
    }
}

之后直接用这个自定义类创建28个按钮,无需添加任何手势识别器,即可支持任意数量的同时触摸。

方案2:调整手势识别器配置(若坚持使用手势)

如果必须保留UILongPressGestureRecognizer,需修改手势的并发规则和事件拦截设置:

class SynthViewController: UIViewController, UIGestureRecognizerDelegate {
    // 假设synthButtons是你的28个按钮数组
    var synthButtons: [UIView] = []

    override func viewDidLoad() {
        super.viewDidLoad()
        setupGestures()
    }

    private func setupGestures() {
        for button in synthButtons {
            let pressGesture = UILongPressGestureRecognizer(target: self, action: #selector(handleButtonPress(_:)))
            pressGesture.minimumPressDuration = 0
            // 禁止手势拦截底层触摸事件
            pressGesture.cancelsTouchesInView = false
            pressGesture.delaysTouchesBegan = false
            pressGesture.delegate = self
            button.addGestureRecognizer(pressGesture)
        }
    }

    @objc private func handleButtonPress(_ gesture: UILongPressGestureRecognizer) {
        guard let button = gesture.view else { return }
        let oscillator = // 获取当前按钮对应的振荡器实例
        switch gesture.state {
        case .began:
            oscillator?.start()
            button.backgroundColor = .systemRed
        case .ended, .cancelled, .failed:
            oscillator?.stop()
            button.backgroundColor = .systemGray
        default: break
        }
    }

    // 允许多个手势同时识别
    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return true
    }
}

额外排查项

  • 检查父视图是否存在其他手势识别器(如滑动、点击),这些手势可能会拦截子视图的触摸事件,需将其cancelsTouchesInView属性设为false
  • 确认AudioKit配置中未设置最大并发音轨限制(你测试仅改颜色也有问题,此概率极低)

内容的提问来源于stack exchange,提问作者Evan Aaron Escobar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 17:05:25