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

iOS Swift钢琴键盘多音实现:如何同时处理多点触摸事件

解决iOS钢琴键盘多音同时触发的问题

嘿,我来帮你搞定这个多音同时播放的问题!从你的日志和代码来看,核心问题在于touchesBegan里的同步操作拖慢了后续触摸事件的处理——虽然AVAudioPlayer.play()本身是异步的,但你的日志、蓝牙发送等同步代码会阻塞主线程,导致第二个触摸事件要等第一个的所有操作完成后才开始执行。以下是具体的解决方案:

优化思路

  1. 区分UI操作与耗时操作:UI相关的状态更新必须留在主线程,但蓝牙发送这类可能耗时的操作要放到后台队列,避免阻塞主线程的触摸事件处理。
  2. 确保音频播放器独立:每个琴键对应独立的AVAudioPlayer实例,不能复用,否则会导致前一个音频被中断。
  3. 异步启动非核心操作:让音频播放和UI状态更新优先执行,耗时操作异步延后处理。

修改后的代码示例

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    for touch in touches {
        let point = touch.location(in: self.stackView)
        guard let hitView = self.stackView.hitTest(point, with: event) else {
            continue
        }
        let tag = hitView.tag
        NSLog("%d first", tag)
        
        // 核心操作立即执行(音频播放是异步启动的,不会阻塞)
        self.pushChanged(senderTag: tag, add: true)
        self.keyPushed(senderTag: tag, userPushed: true)
        self.keyboardTouchStateChanged(senderTag: tag, add: true)
        
        // 把蓝牙发送这类耗时操作放到后台队列,不阻塞主线程
        if self.bluetoothTag == "1" {
            DispatchQueue.global(qos: .userInitiated).async { [weak self] in
                guard let self = self else { return }
                let data = String(tag)
                self.bService.send(colorName: data)
            }
        }
        
        NSLog("%d last", tag)
    }
}

func keyPushed(senderTag:Int, userPushed:Bool = false){
    // 确保每个senderTag对应独立的AVAudioPlayer实例
    guard let player = audioPlayers[senderTag] else { return }
    player.currentTime = 0
    player.play() // play()本身是异步的,会立即返回,不会等待音频播放完成
}

关键说明

  • 日志的先后顺序不代表音频播放的启动顺序:play()方法会立即启动音频播放并返回,所以即使日志里40的last在52的first之前,两个音频其实已经同时开始播放了。
  • 蓝牙操作异步化:把蓝牙发送放到后台队列后,主线程不会被这个操作阻塞,能立刻处理下一个触摸事件。
  • 播放器独立性:务必确认audioPlayers数组中每个索引对应一个全新的AVAudioPlayer实例,每个实例加载对应的音频文件,这样多个音频才能同时发声,不会互相干扰。

内容的提问来源于stack exchange,提问作者加納大地

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 06:42:25