【发布时间】:2018-05-17 02:33:24
【问题描述】:
我看过很多教程,但是当我单击按钮(激活函数播放声音)时,声音没有播放。我看到了stackoverflow推荐的代码,但什么也没有。 我把mp3文件信息asset.xcasset。对吗?
【问题讨论】:
-
您需要添加您尝试过的代码,以便我们为您提供帮助。检查stackoverflow.com/help/how-to-ask
我看过很多教程,但是当我单击按钮(激活函数播放声音)时,声音没有播放。我看到了stackoverflow推荐的代码,但什么也没有。 我把mp3文件信息asset.xcasset。对吗?
【问题讨论】:
SWIFT 4 / XCODE 9.1
import AVFoundation
var objPlayer: AVAudioPlayer?
func playAudioFile() {
guard let url = Bundle.main.url(forResource: "soundName", withExtension: "mp3") else { return }
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback)
try AVAudioSession.sharedInstance().setActive(true)
// For iOS 11
objPlayer = try AVAudioPlayer(contentsOf: url, fileTypeHint: AVFileType.mp3.rawValue)
// For iOS versions < 11
objPlayer = try AVAudioPlayer(contentsOf: url, fileTypeHint: AVFileTypeMPEGLayer3)
guard let aPlayer = objPlayer else { return }
aPlayer.play()
} catch let error {
print(error.localizedDescription)
}
}
【讨论】:
SWIFT 4.2 / XCODE 10.1
请注意,您必须调用
AVAudioSession.sharedInstance().setCategory() 与 Swift 4.2 中的 mode 参数。
import AVFoundation
var audioPlayer: AVAudioPlayer?
func playSound() {
if let audioPlayer = audioPlayer, audioPlayer.isPlaying { audioPlayer.stop() }
guard let soundURL = Bundle.main.url(forResource: "audio_file", withExtension: "wav") else { return }
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category.playback, mode: AVAudioSession.Mode.default)
try AVAudioSession.sharedInstance().setActive(true)
audioPlayer = try AVAudioPlayer(contentsOf: soundURL)
audioPlayer?.play()
} catch let error {
Print.detailed(error.localizedDescription)
}
}
【讨论】:
一个非常简单的解决方案。
import AVFoundation
var myAudioPlayer = AVAudioPlayer?
func playAudioFile() {
let audioFileURL = Bundle.main.url(forResource: "<name-of-file>", withExtension: "mp3/wav/m4a etc.")
do {
try myAudioPlayer = AVAudioPlayer(contentsOf: audioFileURL!)
} catch let error {
print(error.localizedDescription)
}
myAudioPlayer?.play()
}
现在,通过以下方式在任何地方播放此音频文件:playAudioFile()
【讨论】:
将您的 .mp3 文件添加到 Bundle
import AVFoundation
let url = Bundle.main.url(forResource: "SampleAudio", withExtension: "mp3")
let playerItem = AVPlayerItem(url: url!)
let player=AVPlayer(playerItem: playerItem)
let playerLayer=AVPlayerLayer(player: player)
playerLayer.frame = CGRect(x: 0, y: 0, width: 0, height: 0)
self.view.layer.addSublayer(playerLayer)
player.play()
【讨论】:
mp3 作为type 和SampleAudio 作为resource 传递。但是您为什么不建议正确的 API let url = Bundle.main.url(forResource: "SampleAudio", withExtension: "mp3")! 并删除多余的行来创建 URL?
player 和playerItem 创建单独的可选变量?用一行声明和初始化变量,避免显式数据类型的需要。并且请正确处理选项。将! 用于path 很好。但是其他的都不好。
你也可以放一个计时器来显示音乐播放的进度
import AVFoundation
class ViewController: UIViewController {
var player : AVAudioPlayer?
var timer : Timer?
@IBOutlet var pauseBtn: UIButton!
@IBOutlet var replayBtn: UIButton!
@IBAction func rewind2(_ sender: Any) {
}
@IBAction func forward(_ sender: Any) {
var time : TimeInterval = (player?.currentTime)!
time += 5.0
if (time > (player?.duration)!)
{
// stop, track skip or whatever you want
}
else
{
player?.currentTime = time
}
}
@IBOutlet var progress: UIProgressView!
@IBAction func playClicked(_ sender: Any) {
if player == nil {
let resource = Bundle.main.url(forResource: "audioFX", withExtension: "mp3")
do {
player = try AVAudioPlayer(contentsOf: resource!)
player?.isMeteringEnabled = true
player?.prepareToPlay()
} catch let error {
print(error)
}
}
if player != nil {
player?.play()
enableTimer()
player!.delegate = self as? AVAudioPlayerDelegate
}
}
@IBAction func pauseClicked(_ sender: Any) {
if(player != nil){
if(player?.isPlaying == true){
endTimer()
player!.pause()
pauseBtn.setTitle("Resume", for: .normal)
}else{
player!.play()
enableTimer()
pauseBtn.setTitle("Stop", for: .normal)
}
}
}
@IBAction func replayClicked(_ sender: Any) {
if player != nil{
endTimer()
player = nil
pauseBtn.setTitle("Stop", for: .normal)
playClicked(replayBtn)
}
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func enableTimer(){
if(player != nil){
timer = Timer(timeInterval: 0.1, target: self, selector: (#selector(self.updateProgress)), userInfo: nil, repeats: true)
RunLoop.main.add(timer!, forMode: RunLoopMode(rawValue: "NSDefaultRunLoopMode"))
}
}
func endTimer(){
if(timer != nil){
timer!.invalidate()
}
}
@objc func updateProgress(){
if(player != nil){
player!.updateMeters() //refresh state
progress.progress = Float(player!.currentTime/player!.duration)
}
}
}
【讨论】:
Swift 4.2的简单方法:
import AVFoundation
和
let soundEffect = URL(fileURLWithPath: Bundle.main.path(forResource: "btn_click_sound", ofType: "mp3")!)
var audioPlayer = AVAudioPlayer()
@IBAction func buttonClick(sender: AnyObject) {
do {
audioPlayer = try AVAudioPlayer(contentsOf: soundEffect)
audioPlayer.play()
} catch {
// couldn't load file :(
}
}
【讨论】: