从项目访问保存在今天扩展中的文件

Accessing File saved in today extension from project

我正在尝试访问我今天保存的文件 extension.In 我今天的扩展 我这样做是为了保存文件:

func startRecording() {
    let audioFilename = getDocumentsDirectory().appendingPathComponent("recording.m4a")

    let settings = [
        AVFormatIDKey: Int(kAudioFormatMPEG4AAC),
        AVSampleRateKey: 12000,
        AVNumberOfChannelsKey: 1,
        AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue
    ]

    do {
        audioRecorder = try AVAudioRecorder(url: audioFilename, settings: settings)
        audioRecorder.delegate = self
        audioRecorder.record()

        recordButton.setTitle("Stop", for: .normal)
    } catch {
        finishRecording(success: false)
    }
}

func getDocumentsDirectory() -> URL {
    let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
    let documentsDirectory = paths[0]
    return documentsDirectory
}

然后我尝试使用以下代码在项目的主要部分获取我的 AVAudio Player 的数据:

let path = Bundle.main.path(forResource: "recording.m4a", ofType:nil)! let url = URL(fileURLWithPath: path)

但是,它给出了错误:在展开一个 Optional 值时意外发现 nil。 感谢您的帮助。

您的扩展程序将文件保存到其文档目录中,并且您的应用程序代码正在应用程序包中查找该文件。应用程序包仅包含随应用程序分发的资源。您需要深入研究文件系统。

但是,还有一个问题。扩展程序和包含的应用程序不共享文档目录。他们每个人都有自己的容器,用于在本地写入数据。如果您想在它们之间共享数据,则需要多做一些工作。总结:

  1. 为要共享的应用程序和扩展程序创建一个应用程序组标识符。
  2. 使用FileManager.containerURL(forSecurityApplicationGroupIdentifier:)获取共享容器目录的文件URL。
  3. 从容器 URL 追加文件名。
  4. 在扩展程序中,您将像往常一样设置 AVAudioRecorder 并开始录制。
  5. 在主应用程序中,您需要使用 NSFileCoordinator API 来确保一次只有一个进程正在写入文件。希望 AVAudioRecorder 在内部使用 NSFileCoordinator API,尽管我没有立即找到对此的确认。

有关共享容器的更多详细信息,请参阅此 blog post

我只是尝试了同样的方法 - 从 Today Extension 录制音频。代码看起来很眼熟,所以我大胆猜测:您想捕获语音并将文件发送到 Google Speech API,对吗?

尽管如此,我认为我们遇到了扩展限制:根据 https://developer.apple.com/library/content/qa/qa1872/_index.html 判断,扩展无法录制音频。这篇文章是为 iOS 8 写的,但我不相信 Apple 曾经解除过限制。如果我错了,请纠正我,因为我一直 运行 在做 OP 自己做的事情时遇到问题。

顺便说一下,检查 audioRecorder.record() 的结果。它可能是 false 并表明捕获从未开始(这是我当前的错误)。