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

У меня есть аудиофайл (его длина> 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() не вызывается, поэтому представление все еще живо и должно воспроизводить звук до конца.

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
Массив зависимостей в React
Массив зависимостей в React
Все о массиве Dependency и его связи с useEffect.
Toor - Ангулярный шаблон для бронирования путешествий
Toor - Ангулярный шаблон для бронирования путешествий
Toor - Travel Booking Angular Template один из лучших Travel & Tour booking template in the world. 30+ валидированных HTML5 страниц, которые помогут...
1
0
117
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

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

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

Zorgan 21.12.2020 05:00

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

BJ Beecher 21.12.2020 15:02

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