Аудиофайл перестает воспроизводиться через пару секунд

У меня есть аудиофайл (его длина> 60 секунд), который воспроизводится методом onAppear() 2 моих просмотров (показан ниже).

Когда я воспроизвожу аудиофайл в GamesList.swift, он воспроизводится на всю длину. Но если я играю в ActiveGame.swift, то он обрывается через пару секунд. Я не знаю, в чем разница между этими взглядами, но для последнего это не работает.

GamesList.swift (успешно воспроизводит весь файл)

struct GamesList: View {
    @State var showCreateGameSheet = false
    let diameter: CGFloat = 25.0
    @State var games: [Game] = []
    @EnvironmentObject var gameManager: GameManager
    @State var stayPressed = false
    @ObservedObject var soundManager = SoundManager()
    
    var body: some View {
        NavigationView {
            VStack {
                // Create game
                HStack {
                    Spacer()
                    Button(action: { showCreateGameSheet.toggle() }){
                        Text("+ Create game")
                            .font(.custom("Seravek-Medium", size: 20))
                            .foregroundColor(Color.white)
                    }.buttonStyle(GTButton(color: Color("primary"), stayPressed: stayPressed))
                }
                .frame(
                    maxWidth: .infinity,
                    maxHeight: 80,
                    alignment: .top
                )
                ScrollView(.vertical, showsIndicators: true) {
                    ForEach(self.games.sorted(by: { $0.players.count > $1.players.count }), id: \.id){ game in
                        AvailableGame(game: game)
                            .environmentObject(gameManager)
                        Divider()
                    }
                } // Scrollview
            } // VStack
            .padding(25)
//            .navigationBarHidden(true)
            .navigationTitle("Games").foregroundColor(Color("primary"))
            .toolbar {
                ToolbarItem(placement: .navigationBarTrailing) {
                    HStack {
                        Button(action: {
                            self.games = []
                            Database().fetchGames(){ game in
                                if let game = game {
                                    self.games.append(contentsOf: game)
                                }
                            }
                        }){
                            Image(systemName: "arrow.clockwise")
                                .resizable()
                                .aspectRatio(contentMode: .fill)
                                .frame(width: diameter, height: diameter)
                                .foregroundColor(.gray)
                                .padding(.horizontal, 30)
                        }
                        NavigationLink(destination: Settings()){
                            Image("settings")
                                .resizable()
                                .aspectRatio(contentMode: .fill)
                                .frame(width: diameter, height: diameter)
                                .foregroundColor(.gray)
                        }
                    }.padding(.top, 10)
                }
            }
        } // NavigationView
        .sheet(isPresented: $showCreateGameSheet, onDismiss: {  }) {
            CreateGame()
                .environmentObject(self.gameManager)
        }
        .onAppear {
            self.soundManager.playSound(name: "duringGame.aiff", loop: false)
            Database().fetchGames(){ game in
                if let game = game {
                    self.games.append(contentsOf: game)
                }
            }
        }
        .accentColor(Color("primary"))
    }
} 

ActiveGame.swift (вырубается через пару секунд)

struct ActiveGame: View {
    @EnvironmentObject var gameManager: GameManager
    let diameter: CGFloat = 50.0
    @State var image = Image(systemName: "rectangle")
    @ObservedObject var soundManager = SoundManager()
    
    var body: some View {
        ZStack {
            PlayerBlock()
                .padding(.horizontal, 10)
                .position(x: (UIScreen.main.bounds.size.width / 2), y: 30)
            VStack(spacing: 15) {
                ZStack { // Question and answers block
                    if self.gameManager.game?.question == nil {
                        ProgressView()
                            .progressViewStyle(CircularProgressViewStyle())
    //                        .scaleEffect(2.0, anchor: .center)
                    }
                    VStack {
                        Text("Round \(self.gameManager.game?.currentRound ?? 1)")
                            .font(.system(size: 22))
                            .foregroundColor(Color.gray)
                            .multilineTextAlignment(.center)
                            .padding(.bottom, 5)
                        // QUESTION
                        Text("\(self.gameManager.game?.question?.text ?? "")")
                            .font(.custom("Seravek-Bold", size: 28))
                            .foregroundColor(Color("primary"))
                            .multilineTextAlignment(.center)
                            .padding(.horizontal, 30)
                            .fixedSize(horizontal: false, vertical: true)
                        // QUESTION IMAGE
                        (self.gameManager.cachedQuestionImage ?? Image(systemName: "rectangle"))
                            .resizable()
                            .scaledToFit()
                            .aspectRatio(contentMode: .fill)
                            .frame(height: 200)
            //                .frame(width: 280, height: 180)
                            .clipShape(RoundedRectangle(cornerRadius: 10))
                            .padding(.horizontal, 30)
                            .opacity(self.gameManager.cachedQuestionImage == nil ? 0.0 : 1.0) // Hide image while it is loading
                            .onTapGesture {
                                self.gameManager.deleteGame()
                            }
                        // ANSWERS
                        if 1 > 0 {
                            MultipleChoice(options: self.gameManager.game?.question?.options ?? [])
                        } else if (self.gameManager.game?.question?.type == QuestionType.textInput){
                            TextInput()
                        }
                    }.opacity(self.gameManager.game?.question == nil ? 0.0 : 1.0)
                    .disabled(self.gameManager.game?.question == nil)
                    // Hide and disable the question block when the next question is loading
                }
            }.transition(.fadeTransition)
            .padding(.top, 40)
        }
        .onAppear {
            print("onAppear")
            self.soundManager.playSound(name: "duringGame.aiff", loop: false)
        }
        .onDisappear {
            print("onDisappear")
            self.soundManager.player?.stop()
        }
    }
}

SoundManager.swift — это модель представления, которая воспроизводит аудио.

class SoundManager: ObservableObject {
    @Published var player: AVAudioPlayer?
    
    func playSound(name: String, loop: Bool){
        let path = Bundle.main.path(forResource: name, ofType: nil)
        let url = URL(fileURLWithPath: path!)
        print("Play URL from name: \(name)")
        do {
            player = try AVAudioPlayer(contentsOf: url)
            if loop {
                player?.numberOfLoops = -1 // Loop forever
            }
            player?.play()
            print("Played sound") // Both views print this when the audio plays
        } catch {
            print("Error playing \(name) sound")
        }
    }
}

Есть идеи, в чем проблема? SoundManager хранится как наблюдаемый объект в обоих представлениях, поэтому он должен жить, пока живо представление. В ActiveGame onDisappear() не вызывается, поэтому представление все еще живо и должно воспроизводить звук до конца.

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
117
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Первое, что я бы исправил, — это изменение вашей оболочки @ObservedObject на оболочку @StateObject. Это предотвратит освобождение, если представление обновится в какой-то момент в процессе воспроизведения звука. Дай мне знать, если это работает...

Вау, это сработало... Большое спасибо. Таким образом, звуковой менеджер должен был быть уничтожен/освобожден при обновлении представления.

Zorgan 21.12.2020 05:00

Без проблем! Рад, что смог помочь

BJ Beecher 21.12.2020 15:02

Другие вопросы по теме