如何在 AVAudioPlayer 中播放来自 Core Data 的 NSData

How to play NSData from Core Data in AVAudioPlayer

我将 mp3 文件作为 NSData 二进制数据保存到 Core Data 中。然后我在 NSFetchedResultsController 的帮助下加载这个文件。然后我写了下面的代码,但我得到了错误。我该如何解决?

fatal error: unexpectedly found nil while unwrapping an Optional value

var audioPlayer = AVAudioPlayer()
func play() {
    if musicData != nil {
        audioPlayer = AVAudioPlayer(data: musicData, error: nil)
        AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, error: nil)
        AVAudioSession.sharedInstance().setActive(true, error: nil)
        audioPlayer.prepareToPlay()
        audioPlayer.play()
    }
}

更新 我检查了一下,发现 AVAudioPlayer 是零,但我在 class.

的开头初始化了这个播放器

我仍然更改了代码,但我得到了同样的错误 第二种方法

var av = AVAudioPlayer()
func play() {
    let object = fetchedResultsController.fetchedObjects?.first as! Entity
    let songData = object.mp3

    var urlData: NSURL!
    songData.writeToURL(urlData, atomically: true)
    av = AVAudioPlayer(contentsOfURL: urlData, error: nil)
    av.prepareToPlay()
    av.play()
}

我添加了文件类型提示,它对我有用。

  func playMusic() {
        let url = NSBundle.mainBundle().URLForResource("Music", withExtension: "mp3")!
        let data = NSData(contentsOfURL: url)!
        AVAudioSession.sharedInstance().setCategory(AVAudioSessionCategoryPlayback, error: nil)
        AVAudioSession.sharedInstance().setActive(true, error: nil)
        audioPlayer = AVAudioPlayer(data: data, fileTypeHint: AVFileTypeMPEGLayer3, error: nil)
        audioPlayer.prepareToPlay()
        audioPlayer.play()
    }

从 Core Data 播放 mp3 文件时遇到同样的问题。还有另一种解决方案,它不需要您制作资源,而只需要文件管理器。在 Swift 5:

工作
final class AudioPlayer: AVPlayer, ObservableObject {

    private func changeSong(with newSong: Song) { // struct Song has function findInDatabase, which can return saved data from CoreData (or error)

        // trying to find song in CoreData
        newSong.findInDatabase() { (result: Result<SavedSong, CoreDataError>) in

            switch result {
            case .success(let savedSong):
                // SavedSong struct has variable 'file' which is of type Data
                guard let songFile = savedSong.file, !songFile.isEmpty else {
                    // your error handling
                    return
                }

                guard var localURL = FileManager.default.urls(for: .cachesDirectory, in: .userDomainMask).first else { return } // or error handling
                localURL.appendPathComponent("song.mp3")
                try! songFile.write(to: localURL) // saving song data in url

                // now just playing from created URL
                let nextPlayerItem = AVPlayerItem(url: localURL)
                self.replaceCurrentItem(with: nextPlayerItem) // 'self' - is AVPlayer instance
                self.play()

            case .failure( _):
                // error handling, for example try to play from URL
            }

        }

    } 

}