【问题标题】:Swift : Player audio file from another class fileSwift:来自另一个类文件的播放器音频文件
【发布时间】:2016-03-25 20:37:49
【问题描述】:

首先,我只是想让你知道我是 iOS 编程的新手 ;)

我想知道以下情况是否可行,或者我需要以哪种方式更新我的代码以使其工作。 我想播放位于 ViewController 文件 内的播放器类文件 中的音频文件。 我将文件“test.wav”添加到项目的根目录。

我的问题

当我通过点击按钮播放声音时,程序找不到声音文件。我有以下错误消息: 致命错误:在展开可选值时意外发现 nil (lldb)

主 swift 文件:ViewController.swift

import UIKit
import AVFoundation

class ViewController: UIViewController {

    var player1: Player!

    override func viewDidLoad() {
        super.viewDidLoad()

    }

    @IBAction func playAudio(sender: AnyObject) {
        player1.playAudioFile()
    }

}

类文件:Player.swift

import Foundation

import AVFoundation

class Player {

// Variables

    var vc: ViewController!
    var audioFile: AVAudioPlayer!


// Initializer

    init (){

    }

// Methods

    func playAudioFile() {

        if audioFile.playing {
            audioFile.stop()
        } else {
            audioFile.play()
        }
    }

// Intialize ViewController

    init (vc:ViewController!) {

        // Set path for the attack sound

        let audioSnd = NSBundle.mainBundle().pathForResource("test", ofType: "wav")
        let audioFileURL = NSURL(fileURLWithPath: audioSnd!)

        do {

            try audioFile = AVAudioPlayer(contentsOfURL: audioFileURL, fileTypeHint:  nil)
            audioFile.prepareToPlay()

        } catch let err as NSError {
            print(err.debugDescription)
        }
    }
}

更多信息

我的程序有一个“Player”类,还有“Human”和“Monster”等子类。 默认情况下,我的班级播放器有一些用于攻击、死亡等的音频文件。 在某些情况下,“玩家”可以变成人类或怪物,并获得自定义的攻击和死亡声音。

非常感谢您的帮助! ;)

【问题讨论】:

  • 你没有初始化播放器变量。添加:player1 = Player(self)viewDidLoad
  • 其实Player类的原代码比较完整。例如:init (name: String){ self._name = name self._fighterSpr = UIImage (named: "unknown")!但是我遇到了同样的问题,无论如何...... :)
  • 非常感谢德扬,我搞定了。我将更新我的代码,以便我可以在 viewDidLoad 中以这种方式声明 player1。

标签: ios swift


【解决方案1】:

你为什么用 viewController 初始化你的播放器?你不需要那个。

Player 类更改为:

import Foundation
import AVFoundation

class Player {

    // Variables
    var audioFile: AVAudioPlayer!

    // Initializer
    init() {
        // Set path for the attack sound

        let audioSnd = NSBundle.mainBundle().pathForResource("test", ofType: "wav")
        let audioFileURL = NSURL(fileURLWithPath: audioSnd!)

        do {

            try audioFile = AVAudioPlayer(contentsOfURL: audioFileURL, fileTypeHint: nil)
            audioFile.prepareToPlay()
        } catch let err as NSError {
            print(err.debugDescription)
        }
    }

    // Methods
    func playAudioFile() {

        if audioFile.playing {
            audioFile.stop()
        } else {
            audioFile.play()
        }
    }
}

还有你的ViewController.swift

import UIKit
import AVFoundation

class ViewController: UIViewController {

    var player1: Player!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Note, that you need to initialize the player1 variable
        player1 = Player()

    }

    @IBAction func playAudio(sender: AnyObject) {
        player1.playAudioFile()
    }
}

【讨论】:

  • 这真的很有帮助,顺便说一句,import AVFoundation 不需要ViewController ,因为您在单个函数中隔离了音频操作。之前我没有使用全局的player1,而是直接在funcplayAudio中初始化player1 = Player(),然后模拟器没有播放声音,奇怪。
【解决方案2】:

Swift 是函数式编程,因此最好将音频操作和 viewController 分离到不同的文件/类中。然后它们可以在任何场景中重复使用。

音频部分

import AVFoundation

class AudioPlayer {
    // Singleton to keep audio playing anywhere
    static let shared = AudioPlayer()
    var player: AVAudioPlayer?
    
    private init() {}
    
    func play(url: URL) {
        do {
            try AVAudioSession.sharedInstance().setMode(.default)
            try AVAudioSession.sharedInstance().setActive(true, options: .notifyOthersOnDeactivation)
            
            player = try AVAudioPlayer(contentsOf: url)
            guard let player = player else { return }
            player.prepareToPlay()
            player.play()
        } catch {
            print("error occurred")
        }
    }
}

视图控制器

import UIKit

class ViewController: UIViewController {

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

    @IBAction func playAudio(sender: AnyObject) {
        let audioSnd = NSBundle.mainBundle().pathForResource("test", ofType: "wav")
        // don't use force unwrap
        guard let audioFileURL = NSURL(fileURLWithPath: audioSnd) else { return }
        // call the shared instance here
        AudioPlayer.shared.play(url: url)
    }
}

【讨论】:

    猜你喜欢
    • 2012-12-02
    • 2020-08-21
    • 1970-01-01
    • 2023-03-17
    • 1970-01-01
    • 1970-01-01
    • 2017-03-30
    • 2021-04-21
    • 1970-01-01
    相关资源
    最近更新 更多