如何使用Objective-C向/从CoreData保存和获取音频数据?

时间:2016-12-13 16:20:50

标签: ios objective-c xcode core-data

我是iOS开发的新手。

如何使用Objective-C保存和从CoreData获取音频数据?

我只知道我必须使用NSData和二进制数据。

2 个答案:

答案 0 :(得分:4)

正如@shallowThought在评论中所说,通常不应该在Core Data中存储大的二进制数据对象。将声音文件保存到应用程序的文档目录或其他沙箱目录之一,然后在Core Data中存储该文件的URL或路径。

答案 1 :(得分:0)

以为我会添加用于完成我在上面评论中描述的代码。这是在swift 3.0(不是ObjC,对不起)使用CoreData来存储录音(以及图像和视频,尽管这些录制的复制更加复杂,并且未在此处显示)。

我发现最好将录制文件捕获到文件中,然后将其转换为我存储到数据库中的NSData值,再次作为二进制数据类型,并允许选择允许外部存储,CoreData可以执行此操作。

流程首先调用setupAudio()创建单例音频会话,然后使用连接到UI上按钮的startRecordAction()和stopRecordAction()方法来驱动会话(因此使用sharedInstance表示法)。虽然它看起来像是多个会话,但它只是一个共享单例,这个结构让我可以在方法中使用该实例分解进程。

我已经对此进行了简化,因此停止方法会在录制停止时自动将录音添加到数据库中。免责声明:我已经删除了一堆不适用于您的问题的代码,因此我可能添加了一个错误或删除了所需的内容,但我认为它很接近。

以下是代码:

import AVFoundation

...

var audioRecorder:AVAudioRecorder!

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

func directoryURL() -> URL {
    let fileManager = FileManager.default
    let urls = fileManager.urls(for: .documentDirectory, in: .userDomainMask)  
    let documentDirectory = urls[0] as NSURL
    let soundURL = documentDirectory.appendingPathComponent(“capturedAudio.m4a")
    return soundURL!
}

func setupAudio()
{
    let audioSession = AVAudioSession.sharedInstance()

    do {
        unowned let myself = self
        try audioSession.setCategory(AVAudioSessionCategoryPlayAndRecord)
        try audioRecorder = AVAudioRecorder(url: myself.directoryURL(),
                                            settings: recordSettings)
        audioRecorder.prepareToRecord()
    } catch {
        logError...
    }
}

@IBAction func startRecordAction(_ sender: UIButton) {
    if !audioRecorder.isRecording {
        let audioSession = AVAudioSession.sharedInstance()
        do {
            try audioSession.setActive(true)
            audioRecorder.record()
        } catch {
            logError...
        }
    }
}

@IBAction func stopRecordAction(_ sender: UIButton) {
    audioRecorder.stop()
    let audioSession = AVAudioSession.sharedInstance()

    do {
        try audioSession.setActive(false)
    } catch {
        logError...
    }

    var audioTrack: Data?

    do {
        audioTrack = try Data(contentsOf: audioRecorder.url)
    } catch {
        logError...
    }

    addMediaCaptureToDB(audioTrack!, mediaType: "Recording")
}

func addMediaCaptureToDB(_ mediaData: Data, mediaType: String)
{
    guard let newRec = NSEntityDescription.insertNewObject(forEntityName: "MediaCapture", into: context) as? MediaCapture else
    {
        logError...
    }

    newRec.mediaCapture = mediaData as NSData  // Binary Data field / option set to allow External Storage
    newRec.type = mediaType
    newRec.captureDate = NSDate()
    newRec.uniqueID = String(Date().timeIntervalSince1970)

    // Save the new MediaCapture record to the database

    do {
        try context.save()
    } catch {
    logError...
    }
}

希望有帮助...