#swift #swiftui #avaudioplayer
#swift #swiftui #avaudioplayer
Вопрос:
У меня возникла проблема, поскольку я обновил свой Xcode… Если пользователь не нажмет паузу в представлении звука. Мой аудиоплеер продолжает воспроизводиться, когда пользователь меняет представления, однако я бы хотел, чтобы звук останавливался, когда пользователь выходит из режима просмотра проигрывателя (ItemDetail) (например, когда пользователь переходит к просмотру содержимого)
Ранее я использовал приведенное ниже в начале представления содержимого, и это сработало, но теперь это не так:
init() { sounds.pauseSounds() }
Я также пробовал это (что тоже не сработало):
}// end of navigation view .onAppear{sounds.pauseSounds()}
Это мой класс звуков:
class Sounds:ObservableObject {
var player:AVAudioPlayer?
// let shared = Sounds()
func playSounds(soundfile: String) {
if let path = Bundle.main.path(forResource: soundfile, ofType: nil){
do{
player = try AVAudioPlayer(contentsOf: URL(fileURLWithPath: path))
player?.prepareToPlay()
player?.play()
}catch {
print("Error can't find sound file or something's not working with the sounds model")
}
}
}
// This method used to work at pausing the sound (pre-update)
func pauseSounds() {
player?.pause()
}
// over rides the sound defaulting to bluetooth speaker only and sends it to phone speaker if bluetooth is not available (headset/speaker) however if it is available it'll play through that.
func overRideAudio() {
let audioSession = AVAudioSession.sharedInstance()
do {
try audioSession.setCategory(AVAudioSession.Category.playback, mode: .spokenAudio, options: .defaultToSpeaker)
try audioSession.setActive(true, options: .notifyOthersOnDeactivation)
} catch {
print("error.")
}
}
}
И это представление проигрывателя:
struct ItemDetail: View {
@State var isPlaying = false
var item : SessionsItem
@ObservedObject var soundsPlayer = Sounds()
var body: some View {
HStack {
Button(action: {
if self.isPlaying{
// Sounds.player?.pause()
self.isPlaying = false
soundsPlayer.pauseSounds()
}
else{
self.isPlaying = true
soundsPlayer.playSounds(soundfile: "(self.item.name).mp3")
soundsPlayer.overRideAudio()
}
Ответ №1:
Вы создаете другой экземпляр звука, поэтому у вас нет доступа к открытому экземпляру audio’а. Вы можете создать класс Sounds как отдельный экземпляр или передать экземпляр Sounds в detail. Не создавайте новый.
Комментарии:
1. Это сработало (спасибо !!) — в том смысле, что теперь я могу вернуться и приостановить его. Однако, когда я использую: //init() { // Sounds.pauseSounds() // } в представлении содержимого, чтобы отключить все аудио — каким-то образом ничего не воспроизводится, даже в представлениях, в которых я хочу, чтобы аудио воспроизводилось… Почему это должно быть? И есть ли у вас какие-либо другие предложения по подавлению звука в представлении содержимого другим способом?
Ответ №2:
onAppear
это ненадежный способ выполнения подобной SwiftUI
работы, требующий большой предварительной загрузки (это очень очевидно для a List
). Это зависит от устройства и его возможностей. Иногда экраны «появляются», когда они предварительно загружены, не обязательно, когда пользователь смотрит на него.
На List
примере ниже вы можете увидеть это в симуляторе.
На iPhone 8 я получаю 12 onAppear
print
инструкций в консоли при первоначальной загрузке, а на iPhone 12 Pro Max я получаю 17 print
инструкций.
Если ячейки более / менее сложные, вы получаете больше / меньше операторов соответственно. Вы должны найти другой способ сделать это.
import SwiftUI
struct ListCellAppear: View {
var idx: Int
var body: some View {
HStack{
Text(idx.description)
Image(systemName: "checkmark")
}.onAppear(){
print(idx.description)
}
}
}
struct ListAppear: View {
var body: some View {
List(0..<1000){ idx in
ListCellAppear(idx: idx).frame(height: 300)
}
}
}
struct ListAppear_Previews: PreviewProvider {
static var previews: some View {
ListAppear()
}
}
Комментарии:
1. Спасибо, это было на самом деле тоже очень информативно! Если бы я мог принять оба ответа, я бы так и сделал.