繁体   English   中英

AVAudioPlayer在模拟器上工作但不在Real Device上工作

[英]AVAudioPlayer working on Simulator but not on Real Device

当我播放录制的音频时,我收到此错误:

致命错误:在展开Optional值时意外发现nil

在这行代码上:

SoundPlayer = try AVAudioPlayer(contentsOfURL: getFileURL())

但它在模拟器上完美运行,除了真实设备。

ViewController.Swift:

import UIKit
import AVFoundation

class ViewController: UIViewController, AVAudioPlayerDelegate, AVAudioRecorderDelegate {

    @IBOutlet var PlayBTN: UIButton!
    @IBOutlet var RecordBTN: UIButton!


    var soundRecorder : AVAudioRecorder!
    var SoundPlayer : AVAudioPlayer!

    var fileName = "audioFile.m4a"

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        setupRecorder()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    func setupRecorder(){

        let recordSettings = [AVSampleRateKey : NSNumber(float: Float(44100.0)),
            AVFormatIDKey : NSNumber(int: Int32(kAudioFormatMPEG4AAC)),
            AVNumberOfChannelsKey : NSNumber(int: 1),
            AVEncoderAudioQualityKey : NSNumber(int: Int32(AVAudioQuality.Max.rawValue))]

        do{
            try soundRecorder = AVAudioRecorder(URL: getFileURL(), settings: recordSettings)
                soundRecorder.delegate = self
                soundRecorder.prepareToRecord()
        }
        catch let error as NSError {
            error.description
        }

    }

    func getCacheDirectory() -> String {

        let paths = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true) 

        return paths[0]

    }

    func getFileURL() -> NSURL{
        let path  = (getCacheDirectory() as NSString).stringByAppendingPathComponent(fileName)

        let filePath = NSURL(fileURLWithPath: path)


        return filePath
    }


    @IBAction func Record(sender: UIButton) {

        if sender.titleLabel?.text == "Record"{

            soundRecorder.record()
            sender.setTitle("Stop", forState: .Normal)
            PlayBTN.enabled = false

        }
        else{

            soundRecorder.stop()
            sender.setTitle("Record", forState: .Normal)
            PlayBTN.enabled = false
        }

    }

    @IBAction func PlaySound(sender: UIButton) {

        if sender.titleLabel?.text == "Play" {

            RecordBTN.enabled = false
            sender.setTitle("Stop", forState: .Normal)

            preparePlayer()
            SoundPlayer.play()

        }
        else{

            SoundPlayer.stop()
            sender.setTitle("Play", forState: .Normal)

        }

    }

    func preparePlayer(){
        do{
            SoundPlayer = try AVAudioPlayer(contentsOfURL: getFileURL())
            SoundPlayer.delegate = self
            SoundPlayer.volume = 1.0
            SoundPlayer.prepareToPlay()
        }
        catch let error as NSError {
            error.description
        }
    }

    func audioRecorderDidFinishRecording(recorder: AVAudioRecorder, successfully flag: Bool) {
        PlayBTN.enabled = true
    }

    func audioPlayerDidFinishPlaying(player: AVAudioPlayer, successfully flag: Bool) {
        RecordBTN.enabled = true
        PlayBTN.setTitle("Play", forState: .Normal)
    }

    @IBAction func actDone(sender: AnyObject) {
        //viewRecorder.hidden = true

        let fm = NSFileManager.defaultManager()
        let documentsDirectory = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as String

        do {
            let items = try fm.contentsOfDirectoryAtPath(documentsDirectory)

            for item in items {
                print(item)
            }
        }
        catch let error as NSError {
            error.description
        }
    }
}

ViewController.Swift的Storyboard文件:

在此输入图像描述

附加信息:

  • Xcode版本:7.2.1
  • 设备:iPhone 5s
  • iOS版本:9.2.1

注意:我已经寻找类似的SO解决方案,但没有一个帮助我。 其中一些是由于较旧的Swift版本和不推荐使用的方法。 一些解决方案涉及从应用程序包播放音频文件,一些使用Web URL。 所以,这种情况不同( Real Device vs Simulator

以下是Google云端硬盘中源代码的链接。

在真实设备上,需要为setCategory()设置AVAudioSession.sharedInstance()

这里也可以下载固定项目。

func setupRecorder(){

        let audioSession = AVAudioSession.sharedInstance()
        do {
            try audioSession.setCategory(AVAudioSessionCategoryPlayAndRecord)
        } catch let error as NSError {
            print(error.description)
        }

        let recordSettings = [AVSampleRateKey : NSNumber(float: Float(44100.0)),
            AVFormatIDKey : NSNumber(int: Int32(kAudioFormatMPEG4AAC)),
            AVNumberOfChannelsKey : NSNumber(int: 1),
            AVEncoderAudioQualityKey : NSNumber(int: Int32(AVAudioQuality.Max.rawValue))]

        do{
            try soundRecorder = AVAudioRecorder(URL: getFileURL(), settings: recordSettings)
                soundRecorder.delegate = self
                soundRecorder.prepareToRecord()
        }
        catch let error as NSError {
            error.description
        }

    }

注意:音频会话是您的应用和iOS之间的中介,用于配置应用的音频行为。 如果我们为AVAudioSessionCategoryPlayAndRecord设置类别,我们定义iOS音频行为以允许音频输入(录制)和输出(播放)。 参考: 音频会话编程指南

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM