SwiftUI - 更改视图时音频继续播放

SwiftUI - Audio keeps playing when changing views

自从我更新 Xcode 后,我遇到了一个问题...除非用户在音频视图中点击暂停。当用户更改视图时,我的音频播放器继续播放,但我希望音频在用户退出播放器视图 (ItemDetail) 时停止(例如,当用户转到内容视图时)

之前我在内容视图的开头使用了下面的内容,这曾经奏效,但现在没有了:

init() { sounds.pauseSounds() }

我也试过这个(也没用):

}// end of navigation view .onAppear{sounds.pauseSounds()}

这是我的声音class:

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()
                        
                    }

onAppear 不是像这样工作的可靠方法 SwiftUI 做了很多预加载(List 很明显)。这取决于设备及其功能。有时屏幕在预加载时“出现”,不一定在用户查看时出现。

下面的List例子你可以在模拟器中看到。

在 iPhone 8 上,当我最初加载它时,我在控制台中得到 12 onAppear print 语句,在 iPhone 12 Pro Max 上,我得到 17 [=16] =] 语句。

如果单元格 more/less 复杂,您会得到相应的 more/less 语句。你应该找到另一种方法来做到这一点。

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()
    }
}

您正在创建另一个声音实例,因此您无权访问打开的音频实例。您可以将 Sounds class 作为单个实例或将 Sounds 实例传递给细节。不要创建一个新的。