【发布时间】:2019-07-17 05:11:51
【问题描述】:
在基于 SwiftUI 的应用程序中放置音频播放代码的最佳位置是哪里,即没有 UIViewController 类?我要播放的声音是由一个视图发起的,所以我想把它放到对应的视图模型类中。但由于模型类是关于数据的,我认为应该有更好的选择。最好的架构是什么?
【问题讨论】:
标签: swift audio avfoundation avaudioplayer swiftui
在基于 SwiftUI 的应用程序中放置音频播放代码的最佳位置是哪里,即没有 UIViewController 类?我要播放的声音是由一个视图发起的,所以我想把它放到对应的视图模型类中。但由于模型类是关于数据的,我认为应该有更好的选择。最好的架构是什么?
【问题讨论】:
标签: swift audio avfoundation avaudioplayer swiftui
正确,视图不应该处理数据。 SwiftUI 强制执行此逻辑。
您可以创建一个播放器类来负责播放音频。并将其添加为EnvironmentObject,这样您就可以使用View 中的按钮来控制它。然后,您可以做一些甜蜜的事情,例如绑定您的播放按钮以根据播放器是否正在播放不同的图像:)
更新
Xcode 11 beta 4 的代码已更新(willChange 而不是 didChange)
struct PlayerView : View {
@EnvironmentObject private var player: Player
var body: some View {
Button(action: {
self.player.pauseOrPlay()
}) {
Image(systemName: player.isPlaying ? "pause.circle.fill" : "play.circle.fill").font(.title).frame(minWidth: 44, minHeight: 44)
}
}
}
class Player: BindableObject {
let willChange = PassthroughSubject<Player, Never>()
var isPlaying: Bool = false {
willSet {
willChange.send(self)
}
}
func pauseOrPlay() {
// Code that toggles the audio on and off
}
}
【讨论】:
BindableObject 已更改为 ObservableObject 参见:developer.apple.com/documentation/combine/observableobject
尽管 Davide 的解决方案有效,但我最终还是使用了单例模式来全局访问我的声音播放器对象,并且实际上将声音的触发从视图移回了模型类。
看起来像这样:
class Player {
static let shared = AudioPlayer()
func pauseOrPlay() {
// Code that toggles the audio on and off
}
}
我现在可以从任何地方调用它:
Player.shared.pauseOrPlay()
【讨论】: