[导入AudioKit并尝试运行一个小示例时,我得到:
Error Domain=com.apple.dt.ultraviolet.service Code=12 "Rendering service was interrupted" UserInfo={NSLocalizedDescription=Rendering service was interrupted}
经过大量的测试,我注意到它仅在“预览(右侧)”模式下崩溃,因为它“构建”并在“模拟器”中运行。它是Xcode中preview
功能的限制吗?我不知道,但已报告给AudioKit团队(https://github.com/AudioKit/AudioKit/issues/2034)
考虑到[hello world
]中发布的https://audiokit.io/examples/HelloWorld/,我对它进行了一些不同的改写,以适应最新的(考虑到撰写本文时)Xcode 11.4和Swift 5.2:
import SwiftUI
import AudioKit
struct ContentView: View {
var oscillator = AKOscillator()
var body: some View {
VStack {
Button("Play") {
self.playSound()
}
}.onAppear {
do {
AudioKit.output = self.oscillator
try AudioKit.start()
} catch {
print("audiokit init error")
}
}
}
private func playSound(){
self.oscillator.amplitude = 1
self.oscillator.frequency = 440
self.oscillator.start()
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Podfile是:
platform :ios, '11.0'
target 'AKHello' do
use_frameworks!
# Pods for AKHello
pod 'AudioKit', '~> 4.9.5'
end
源代码中是否存在语法错误,或者是获取更有意义或更有用的错误来解决此问题的方法?考虑到github页面(https://github.com/AudioKit/AudioKit/releases中的发行说明),AudioKit似乎与最新的Xcode 11.4兼容,您可以阅读“此版本主要是为了通过CocoaPods带来与最新Xcode发行版兼容的新二进制文件”]
由于在View
中初始化AudioKit可能不是一个好习惯(尽管目标只是运行一个简单的Hello世界,只是要确保我将该部分移至struct
中,但同样的问题也会发生)
// AudioPlayer.swift
import AudioKit
struct AudioPlayer {
var oscillator = AKOscillator()
init() {
do {
AudioKit.output = self.oscillator
try AudioKit.start()
} catch {
print("audiokit init error")
}
}
func playSound(){
self.oscillator.amplitude = 1
self.oscillator.frequency = 440
self.oscillator.start()
}
}
// ContentView.swift
import SwiftUI
struct ContentView: View {
var audioPlayer: AudioPlayer = AudioPlayer()
var body: some View {
VStack {
Button("Play") {
self.audioPlayer.playSound()
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
也尝试观察,在内容视图和场景委托中分别进行了更改,我在其中传递了音频播放器的新类:
// ContentView.swift
import SwiftUI
struct ContentView: View {
@ObservedObject var audioPlayer: AudioPlayer
var body: some View {
VStack {
Button("Play") {
self.audioPlayer.playSound()
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView(audioPlayer: AudioPlayer())
}
}
// AudioPlayer.swift
import AudioKit
import Combine
class AudioPlayer: ObservableObject {
let objectWillChange = PassthroughSubject<AudioPlayer, Never>()
var isPlaying = false {
didSet {
objectWillChange.send(self)
}
}
var oscillator = AKOscillator()
init() {
do {
AudioKit.output = self.oscillator
try AudioKit.start()
isPlaying = true
} catch {
print("audiokit init error")
}
}
func playSound(){
self.oscillator.amplitude = 1
self.oscillator.frequency = 440
self.oscillator.start()
}
}
// SceneDelegate.swift
import UIKit
import SwiftUI
class SceneDelegate: UIResponder, UIWindowSceneDelegate {
var window: UIWindow?
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
let contentView = ContentView(audioPlayer: AudioPlayer())
if let windowScene = scene as? UIWindowScene {
let window = UIWindow(windowScene: windowScene)
window.rootViewController = UIHostingController(rootView: contentView)
self.window = window
window.makeKeyAndVisible()
}
}
}
我不确定这是否是您的全部问题,但不要指望AudioKit在“预览”视图中工作。据我所知,应该只是可视化SwiftUI类型的东西。 AudioKit的生命周期与SwiftUI相关联的第一种方法非常危险。请记住,SwiftUI会做任何需要做的神奇事情,并且您不应该信任音频系统在其中运行。然后,您将音频播放器的内容移到了自己的类中,但是我仍然担心您将生命周期与SwiftUI结构联系得太紧。我的方法是将音频引擎移到在SceneDelegate中创建的自己的类中,然后在onAppear上启动主要内容视图。有关如何设置此示例的示例,请参见iOS + Catalyst / Drums /的AudioKit示例文件夹。顺便提一下,应该在StackOverflow上询问此问题,以便其他人可以更轻松地从中受益。 (也许是在SO上,我只是没有注意到?)