实时更新滑块值 AVAudioPlayer SwiftUI
Updating slider value in real time AVAudioPlayer SwiftUI
所以我有一个class调用的音频设置如下:
class audioSettings: ObservableObject {
var audioPlayer: AVAudioPlayer?
var playing = false
var playValue: TimeInterval = 0.0
var playerDuration: TimeInterval = 146
var timer = Timer.publish(every: 0.1, on: .main, in: .common).autoconnect()
func playSound(sound: String, type: String) {
if let path = Bundle.main.path(forResource: sound, ofType: type) {
do {
if playing == false {
if (audioPlayer == nil) {
audioPlayer = try AVAudioPlayer(contentsOf: URL(fileURLWithPath: path))
audioPlayer?.prepareToPlay()
audioPlayer?.play()
playing = true
}
}
if playing == false {
audioPlayer?.play()
playing = true
}
} catch {
print("Could not find and play the sound file.")
}
}
}
func stopSound() {
// if playing == true {
audioPlayer?.stop()
audioPlayer = nil
playing = false
playValue = 0.0
// }
}
func pauseSound() {
if playing == true {
audioPlayer?.pause()
playing = false
}
}
func changeSliderValue() {
if playing == true {
pauseSound()
audioPlayer?.currentTime = playValue
}
if playing == false {
audioPlayer?.play()
playing = true
}
}
}
当我在视图中实现代码时,我成功播放了文件。我成功地停止了它,我也成功地移动了滑块并在音频中获得了新的位置。
我遇到困难的地方在于如何让滑块在播放音频时实时更新。如果我点击播放,在我点击暂停之前,滑块将不会执行任何操作。此时它将移动到正确的位置。
查看代码如下:
struct myExperienceFearChunk: View {
@ObservedObject var audiosettings = audioSettings()
var body: some View {
HStack {
Button(action: {
if (self.playButton == Image(systemName: "play.circle")) {
print("All Done")
self.audiosettings.playSound(sound: "audio file", type: "mp3")
self.audiosettings.timer = Timer.publish(every: 0.1, on: .main, in: .common).autoconnect()
self.playButton = Image(systemName: "pause.circle")
} else {
self.audiosettings.pauseSound()
self.playButton = Image(systemName: "play.circle")
}
}) {
self.playButton
.foregroundColor(Color.white)
.font(.system(size: 44))
}
Button(action: {
print("All Done")
self.audiosettings.stopSound()
self.playButton = Image(systemName: "play.circle")
self.audiosettings.playValue = 0.0
}) {
self.stopButton
.foregroundColor(Color.white)
.font(.system(size: 44))
}
}
Slider(value: $audiosettings.playValue, in: TimeInterval(0.0)...audiosettings.playerDuration, onEditingChanged: { _ in
self.audiosettings.changeSliderValue()
})
.onReceive(audiosettings.timer) { _ in
if self.audiosettings.playing {
if let currentTime = self.audiosettings.audioPlayer?.currentTime {
self.audiosettings.playValue = currentTime
if currentTime == TimeInterval(0.0) {
self.audiosettings.playing = false
}
}
}
else {
self.audiosettings.playing = false
self.audiosettings.timer.upstream.connect().cancel()
}
}
}
}
}
我知道 .onReceive 是我点击暂停时滑块更新的地方,因为没有它滑块根本不会更新,除非被拖动。
关于如何让滑块在播放音频时更新设置 playValue 的任何想法。
谢谢。
这里是固定代码。使用 Xcode 11.4 / iOS 13.4
测试
修复的主要内容是发布 @Published var playValue
以便观察到的对象有机会收到有关 audioSettings
中的变化的通知,从而更新 Slider
... 其他是次要的.
class audioSettings: ObservableObject {
var audioPlayer: AVAudioPlayer?
var playing = false
@Published var playValue: TimeInterval = 0.0
var playerDuration: TimeInterval = 146
var timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
func playSound(sound: String, type: String) {
if let path = Bundle.main.path(forResource: sound, ofType: type) {
do {
if playing == false {
if (audioPlayer == nil) {
audioPlayer = try AVAudioPlayer(contentsOf: URL(fileURLWithPath: path))
audioPlayer?.prepareToPlay()
audioPlayer?.play()
playing = true
}
}
if playing == false {
audioPlayer?.play()
playing = true
}
} catch {
print("Could not find and play the sound file.")
}
}
}
func stopSound() {
// if playing == true {
audioPlayer?.stop()
audioPlayer = nil
playing = false
playValue = 0.0
// }
}
func pauseSound() {
if playing == true {
audioPlayer?.pause()
playing = false
}
}
func changeSliderValue() {
if playing == true {
pauseSound()
audioPlayer?.currentTime = playValue
}
if playing == false {
audioPlayer?.play()
playing = true
}
}
}
struct myExperienceFearChunk: View {
@ObservedObject var audiosettings = audioSettings()
@State private var playButton: Image = Image(systemName: "play.circle")
var body: some View {
VStack {
HStack {
Button(action: {
if (self.playButton == Image(systemName: "play.circle")) {
print("All Done")
self.audiosettings.playSound(sound: "filename", type: "wav")
self.audiosettings.timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
self.playButton = Image(systemName: "pause.circle")
} else {
self.audiosettings.pauseSound()
self.playButton = Image(systemName: "play.circle")
}
}) {
self.playButton
.foregroundColor(Color.white)
.font(.system(size: 44))
}
Button(action: {
print("All Done")
self.audiosettings.stopSound()
self.playButton = Image(systemName: "play.circle")
self.audiosettings.playValue = 0.0
}) {
Image(systemName: "stop.circle")
.foregroundColor(Color.white)
.font(.system(size: 44))
}
}
Slider(value: $audiosettings.playValue, in: TimeInterval(0.0)...audiosettings.playerDuration, onEditingChanged: { _ in
self.audiosettings.changeSliderValue()
})
.onReceive(audiosettings.timer) { _ in
if self.audiosettings.playing {
if let currentTime = self.audiosettings.audioPlayer?.currentTime {
self.audiosettings.playValue = currentTime
if currentTime == TimeInterval(0.0) {
self.audiosettings.playing = false
}
}
}
else {
self.audiosettings.playing = false
self.audiosettings.timer.upstream.connect().cancel()
}
}
}
}
}
所以我有一个class调用的音频设置如下:
class audioSettings: ObservableObject {
var audioPlayer: AVAudioPlayer?
var playing = false
var playValue: TimeInterval = 0.0
var playerDuration: TimeInterval = 146
var timer = Timer.publish(every: 0.1, on: .main, in: .common).autoconnect()
func playSound(sound: String, type: String) {
if let path = Bundle.main.path(forResource: sound, ofType: type) {
do {
if playing == false {
if (audioPlayer == nil) {
audioPlayer = try AVAudioPlayer(contentsOf: URL(fileURLWithPath: path))
audioPlayer?.prepareToPlay()
audioPlayer?.play()
playing = true
}
}
if playing == false {
audioPlayer?.play()
playing = true
}
} catch {
print("Could not find and play the sound file.")
}
}
}
func stopSound() {
// if playing == true {
audioPlayer?.stop()
audioPlayer = nil
playing = false
playValue = 0.0
// }
}
func pauseSound() {
if playing == true {
audioPlayer?.pause()
playing = false
}
}
func changeSliderValue() {
if playing == true {
pauseSound()
audioPlayer?.currentTime = playValue
}
if playing == false {
audioPlayer?.play()
playing = true
}
}
}
当我在视图中实现代码时,我成功播放了文件。我成功地停止了它,我也成功地移动了滑块并在音频中获得了新的位置。
我遇到困难的地方在于如何让滑块在播放音频时实时更新。如果我点击播放,在我点击暂停之前,滑块将不会执行任何操作。此时它将移动到正确的位置。
查看代码如下:
struct myExperienceFearChunk: View {
@ObservedObject var audiosettings = audioSettings()
var body: some View {
HStack {
Button(action: {
if (self.playButton == Image(systemName: "play.circle")) {
print("All Done")
self.audiosettings.playSound(sound: "audio file", type: "mp3")
self.audiosettings.timer = Timer.publish(every: 0.1, on: .main, in: .common).autoconnect()
self.playButton = Image(systemName: "pause.circle")
} else {
self.audiosettings.pauseSound()
self.playButton = Image(systemName: "play.circle")
}
}) {
self.playButton
.foregroundColor(Color.white)
.font(.system(size: 44))
}
Button(action: {
print("All Done")
self.audiosettings.stopSound()
self.playButton = Image(systemName: "play.circle")
self.audiosettings.playValue = 0.0
}) {
self.stopButton
.foregroundColor(Color.white)
.font(.system(size: 44))
}
}
Slider(value: $audiosettings.playValue, in: TimeInterval(0.0)...audiosettings.playerDuration, onEditingChanged: { _ in
self.audiosettings.changeSliderValue()
})
.onReceive(audiosettings.timer) { _ in
if self.audiosettings.playing {
if let currentTime = self.audiosettings.audioPlayer?.currentTime {
self.audiosettings.playValue = currentTime
if currentTime == TimeInterval(0.0) {
self.audiosettings.playing = false
}
}
}
else {
self.audiosettings.playing = false
self.audiosettings.timer.upstream.connect().cancel()
}
}
}
}
}
我知道 .onReceive 是我点击暂停时滑块更新的地方,因为没有它滑块根本不会更新,除非被拖动。
关于如何让滑块在播放音频时更新设置 playValue 的任何想法。
谢谢。
这里是固定代码。使用 Xcode 11.4 / iOS 13.4
测试修复的主要内容是发布 @Published var playValue
以便观察到的对象有机会收到有关 audioSettings
中的变化的通知,从而更新 Slider
... 其他是次要的.
class audioSettings: ObservableObject {
var audioPlayer: AVAudioPlayer?
var playing = false
@Published var playValue: TimeInterval = 0.0
var playerDuration: TimeInterval = 146
var timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
func playSound(sound: String, type: String) {
if let path = Bundle.main.path(forResource: sound, ofType: type) {
do {
if playing == false {
if (audioPlayer == nil) {
audioPlayer = try AVAudioPlayer(contentsOf: URL(fileURLWithPath: path))
audioPlayer?.prepareToPlay()
audioPlayer?.play()
playing = true
}
}
if playing == false {
audioPlayer?.play()
playing = true
}
} catch {
print("Could not find and play the sound file.")
}
}
}
func stopSound() {
// if playing == true {
audioPlayer?.stop()
audioPlayer = nil
playing = false
playValue = 0.0
// }
}
func pauseSound() {
if playing == true {
audioPlayer?.pause()
playing = false
}
}
func changeSliderValue() {
if playing == true {
pauseSound()
audioPlayer?.currentTime = playValue
}
if playing == false {
audioPlayer?.play()
playing = true
}
}
}
struct myExperienceFearChunk: View {
@ObservedObject var audiosettings = audioSettings()
@State private var playButton: Image = Image(systemName: "play.circle")
var body: some View {
VStack {
HStack {
Button(action: {
if (self.playButton == Image(systemName: "play.circle")) {
print("All Done")
self.audiosettings.playSound(sound: "filename", type: "wav")
self.audiosettings.timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
self.playButton = Image(systemName: "pause.circle")
} else {
self.audiosettings.pauseSound()
self.playButton = Image(systemName: "play.circle")
}
}) {
self.playButton
.foregroundColor(Color.white)
.font(.system(size: 44))
}
Button(action: {
print("All Done")
self.audiosettings.stopSound()
self.playButton = Image(systemName: "play.circle")
self.audiosettings.playValue = 0.0
}) {
Image(systemName: "stop.circle")
.foregroundColor(Color.white)
.font(.system(size: 44))
}
}
Slider(value: $audiosettings.playValue, in: TimeInterval(0.0)...audiosettings.playerDuration, onEditingChanged: { _ in
self.audiosettings.changeSliderValue()
})
.onReceive(audiosettings.timer) { _ in
if self.audiosettings.playing {
if let currentTime = self.audiosettings.audioPlayer?.currentTime {
self.audiosettings.playValue = currentTime
if currentTime == TimeInterval(0.0) {
self.audiosettings.playing = false
}
}
}
else {
self.audiosettings.playing = false
self.audiosettings.timer.upstream.connect().cancel()
}
}
}
}
}