在其他 swift 文件中调用时,AVAudioPlayer 不会播放声音

Posted

技术标签:

【中文标题】在其他 swift 文件中调用时,AVAudioPlayer 不会播放声音【英文标题】:AVAudioPlayer wont play sound when called in other swift file 【发布时间】:2015-06-13 17:18:59 【问题描述】:

我有两个 swift 文件 - 我的 ViewController:UIViewController 和 AudioPlayer:AVAudioPlayer。

我的 AudioPlayer 文件有这个功能

func seaGullSound() 

    var tmp = AVAudioPlayer()

    var seaGullSound = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("Gulls", ofType: "mp3")!)

    AVAudiosession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, error: nil)
    AVAudioSession.sharedInstance().setActive(true, error: nil)

    var error:NSError?

    tmp = AVAudioPlayer(contentsOfURL: seaGullSound, error: &error)
    tmp.prepareToPlay()
    tmp.play()

    println("This function got called!")

我正在尝试通过点击一个按钮在我的 ViewController 中调用该函数,使用以下代码:

@IBAction func playSound(sender: AnyObject) 
    var audio = AudioPlayer()
    audio.seaGullSound()

单击按钮时没有播放声音。但是,打印语句有效。如果我将 seaGullSound() 移动到 ViewController 文件,我可以播放音频,所以我知道 mp3 确实有效。我没有将音频移至 ViewController,因为我想养成不将所有代码都挤到一个文件中的习惯。提前感谢您的帮助。

编辑:

class HighScore: UIViewController 

var audioInitializer = AudioPlayer()

func updateHighScore(score:Int) -> String 
    NSUserDefaults.standardUserDefaults().integerForKey("highscore")

    //Check if score is higher than NSUserDefaults stored value and change NSUserDefaults stored value if it's true
    if score > NSUserDefaults.standardUserDefaults().integerForKey("highscore") 
        //call applause sound
        audioInitializer.applauseSound()
        //set score
        NSUserDefaults.standardUserDefaults().setInteger(score, forKey: "highscore")
        NSUserDefaults.standardUserDefaults().synchronize()
    
    NSUserDefaults.standardUserDefaults().integerForKey("highscore")

    //use below line to reset high score for testing
    //NSUserDefaults.standardUserDefaults().removeObjectForKey("highscore")

    return String(NSUserDefaults.standardUserDefaults().integerForKey("highscore"))

这是包含声音的文件:

class AudioPlayer: AVAudioPlayer 

var soundMaster = AVAudioPlayer()

func tappingSound() 

    var tapSoundURL = NSBundle.mainBundle().URLForResource("tapSound", withExtension: "mp3")

    AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, error: nil)
    AVAudioSession.sharedInstance().setActive(true, error: nil)

    var error:NSError?

    soundMaster = AVAudioPlayer(contentsOfURL: tapSoundURL, error: &error)
    soundMaster.prepareToPlay()
    soundMaster.play()


//need to call in highscore.swift
func applauseSound() 
    var tapSoundURL = NSBundle.mainBundle().URLForResource("applause", withExtension: "mp3")

    AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, error: nil)
    AVAudioSession.sharedInstance().setActive(true, error: nil)

    var error:NSError?

    soundMaster = AVAudioPlayer(contentsOfURL: tapSoundURL, error: &error)
    soundMaster.prepareToPlay()
    soundMaster.play()
    println("did this get called?")

【问题讨论】:

【参考方案1】:

您只需将 tmp AVAudioPlayer 的声明移出您的方法。将其声明为类变量。

您还应该使用 URLForResource 而不是 pathForResource:

let seaGullSoundURL = NSBundle.mainBundle().URLForResource("Gulls", withExtension:  "mp3")!

试试这样:

import UIKit
import AVFoundation
class HighScore: UIViewController 
    var audioPlayer = AVAudioPlayer()
    override func viewDidLoad() 
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    
    override func didReceiveMemoryWarning() 
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    
    func updateHighScore(score:Int) -> String 
        //Check if score is higher than NSUserDefaults stored value and change NSUserDefaults stored value if it's true
        if score > NSUserDefaults().integerForKey("highscore") 
            //call applause sound
            playAudio("applause")
            //set score
            NSUserDefaults().setInteger(score, forKey: "highscore")
        
        //use below line to reset high score for testing
        //NSUserDefaults.standardUserDefaults().removeObjectForKey("highscore")
        return NSUserDefaults().integerForKey("highscore").description
    
    func playAudio(audioName: String ) 
        var error:NSError?
        if let audioURL = NSBundle.mainBundle().URLForResource(audioName, withExtension: "mp3") 
            audioPlayer = AVAudioPlayer(contentsOfURL: audioURL, error: &error)
            audioPlayer.prepareToPlay()
            audioPlayer.play()
         else if let error = error 
            println(error.description)
        
    
    @IBAction func playSound(sender: UIButton) 
        playAudio("Gulls")
    

【讨论】:

哇,非常感谢你:) ...当我允许大声笑时,我会在几分钟内接受你的回答。并感谢您的快速回复...您能解释一下为什么我必须在课堂上给他们打电话吗? 如果你在方法中声明它,当它结束方法的执行时它们将不复存在 有趣的是,我遇到了和以前一样的问题,除了另一个文件。我按照您的更正,但它不会播放声音,但仍会执行打印语句 所有声音都会发生这种情况 您不需要自定义类来播放声音。您只需要一个方法,我会为您发布一个

以上是关于在其他 swift 文件中调用时,AVAudioPlayer 不会播放声音的主要内容,如果未能解决你的问题,请参考以下文章

音频未在 SwiftUI 中播放

从 Swift 中的其他类调用方法

textFieldDidEndEditing 未在 swift 中调用

不能在代码中调用 segue (Swift)

Swift5 新特性预览

应用程序中的调用函数didbecomeactive - Swift 2.0