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

Swift4 修改循环播放逻辑实现交替切换音效的技术求助

实现交替播放两种音效的修改方案

嘿,我看了你的代码,要把单一音效重复播放改成交替播放两种音效(比如ababab)其实很容易,咱们来调整几个关键地方就行:

问题分析

你当前的代码只用了一个AVAudioPlayer实例,每次定时器触发都播放同一个音效,自然没法切换。咱们需要两个播放器实例分别对应两种音效,再加上一个变量来跟踪当前该播放哪一个,就能实现交替效果了。

修改步骤&完整代码

下面是修改后的代码,我标注了关键改动的地方:

import UIKit
import AVFoundation

class ViewController: UIViewController {
    @IBOutlet weak var whiste: UIImageView!
    @IBOutlet weak var textField: UITextField! // 播放次数输入框
    @IBOutlet weak var textfield2: UITextField! // 间隔时长输入框
    
    // 用数组存储两个音效的播放器(代替原来的单个player)
    var soundPlayers: [AVAudioPlayer] = []
    var timer = Timer()
    var count: Int = 0
    // 新增:跟踪当前要播放的音效索引(0或1,对应两种音效)
    var currentSoundIndex = 0

    override func viewDidLoad() {
        super.viewDidLoad()
        // 提前加载两个音效,避免点击按钮时才加载导致延迟
        loadSoundFiles()
    }
    
    // 加载两个音效文件到播放器数组
    func loadSoundFiles() {
        // 第一个音效:regularWHistle.wav
        if let soundPath1 = Bundle.main.path(forResource: "regularWHistle", ofType: "wav"),
           let soundURL1 = URL(fileURLWithPath: soundPath1) {
            do {
                let player1 = try AVAudioPlayer(contentsOf: soundURL1)
                player1.prepareToPlay() // 预加载,提升播放流畅度
                soundPlayers.append(player1)
            } catch {
                print("加载第一个音效失败:\(error.localizedDescription)")
            }
        }
        
        // 第二个音效:这里假设你的第二个音效叫"anotherWhistle.wav",记得替换成你实际的文件名
        if let soundPath2 = Bundle.main.path(forResource: "anotherWhistle", ofType: "wav"),
           let soundURL2 = URL(fileURLWithPath: soundPath2) {
            do {
                let player2 = try AVAudioPlayer(contentsOf: soundURL2)
                player2.prepareToPlay()
                soundPlayers.append(player2)
            } catch {
                print("加载第二个音效失败:\(error.localizedDescription)")
            }
        }
    }

    @IBAction func playButtonTapped(_ sender: Any) {
        // 先检查两个音效是否都加载成功
        guard soundPlayers.count == 2 else {
            let alert = UIAlertController(title: "错误", message: "音效文件加载失败,请检查文件名是否正确", preferredStyle: .alert)
            alert.addAction(UIAlertAction(title: "OK", style: .cancel))
            present(alert, animated: true)
            return
        }
        
        // 验证播放次数输入
        guard let textValue = textField.text, let repeatCount = Int(textValue), repeatCount > 0 else {
            let alert = UIAlertController(title: "提示", message: "请输入有效的播放次数(大于0的整数)", preferredStyle: .alert)
            alert.addAction(UIAlertAction(title: "OK", style: .cancel))
            present(alert, animated: true)
            return
        }
        
        // 开始播放逻辑
        playWith(repeatCount: repeatCount)
    }
    
    func playWith(repeatCount: Int) {
        // 先停止之前的定时器和播放,避免重复触发
        timer.invalidate()
        count = 0
        currentSoundIndex = 0 // 重置为第一个音效开始
        
        // 获取间隔时长,默认0.36秒
        var timeInterval = 0.36
        if let textValue = textfield2.text, let inputInterval = Double(textValue), inputInterval > 0 {
            timeInterval = inputInterval
        }
        
        // 先播放第一个音效
        soundPlayers[currentSoundIndex].play()
        currentSoundIndex = 1 - currentSoundIndex // 切换到下一个音效
        
        // 启动定时器
        timer = Timer.scheduledTimer(withTimeInterval: timeInterval, repeats: true) { [weak self] timer in
            guard let self = self else { return }
            self.count += 1
            
            if self.count < repeatCount {
                // 播放当前索引的音效,然后切换索引实现交替
                self.soundPlayers[self.currentSoundIndex].play()
                self.currentSoundIndex = 1 - self.currentSoundIndex
            } else {
                // 播放次数达标,停止所有播放和定时器
                self.soundPlayers.forEach { $0.stop() }
                timer.invalidate()
                self.count = 0
            }
        }
    }
}

关键改动说明

  • 新增loadSoundFiles方法:在viewDidLoad时提前加载两个音效,避免点击按钮时的延迟,同时用prepareToPlay预加载提升播放流畅度。
  • 用数组存储两个播放器:soundPlayers数组分别存两种音效的播放器,代替原来的单个player变量。
  • currentSoundIndex变量:用来跟踪当前要播放的音效索引,每次播放后切换成1 - currentSoundIndex(0变1,1变0),实现交替效果。
  • 完善输入验证:新增了音效加载失败的提示,确保两个音效都准备好才开始播放;同时保留了原有的输入合法性校验。
  • 避免重复触发:每次点击播放按钮时先停止之前的定时器和播放,防止多个定时器同时运行导致混乱。

记得把代码里的anotherWhistle.wav替换成你实际的第二个音效文件名哦~

内容的提问来源于stack exchange,提问作者user8105388

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:34:49