0

I'm using SWIFTUI for IOS16 development. I have a view with a navigation link that used to work great, but now that I have added an onTapGesture, stopped working. This is my code:

import SwiftUI
import AVKit

struct SpecialVideo6: View {
    let videoURL = Bundle.main.url(forResource: "war", withExtension: "mp4")!
    @Binding var path: NavigationPath

    var player: AVPlayer {
        let player = AVPlayer(url: videoURL)
        player.play()
        return player
    }

    var body: some View {
        ZStack {
            Color(.black).ignoresSafeArea()
            VideoPlayer(player: player)
                .scaledToFill()
            HStack{
                Spacer()
                VStack {
                    NavigationLink("", value: Route.linkSpecials).buttonStyle(BtnVid(vidIcon: "share"))
                    NavigationLink("", value: Route.linkSpecials).buttonStyle(BtnVid(vidIcon: "hearth"))
                    Spacer()
                }.frame(maxHeight: 330).padding(.trailing, 16).padding(.top, 50)
            }
            VStack {
                Spacer()
                NavigationLink("Bet", value: Route.linkBetBlackOps).buttonStyle(BtnFull2(player: player))
            }.frame(maxHeight: 330)
        }
        .navigationBarBackButtonHidden()
        .toolbar {
                ToolbarItem(placement: .navigationBarTrailing) {
                    Button {
                        path.removeLast()
                    } label: {
                        HStack(spacing: 0) {
                            Spacer()
                            Image("x")
                        }.padding(.top, 25)
                    }
                }
        }
    }
}

struct BtnFull2: ButtonStyle {
    let player: AVPlayer? // Add a parameter to store the AVPlayer instance
    
    func makeBody(configuration: Configuration) -> some View {
        configuration.label
            .font(.custom("Bebas Neue", size: 24))
            .foregroundColor(.white)
            .frame(width: 98, height: 50)
            .background(LinearGradient(gradient: Gradient(colors: [Color("lb"), Color("rb")]),startPoint: .top, endPoint: .bottom))
            .cornerRadius(10)
            .onTapGesture {
                player?.pause() // Use the player instance passed as a parameter
            }
    }
}

Can anyone tell me how to fix it? What I am trying to do is to stop the video from playing when going on that link, right now the video sound keep on playing.

Pro Girl
  • 762
  • 7
  • 21
  • Can you elaborate on what do you mean by stopped working? Do you get an error on Xcode or is it at runtime? – vicegax Mar 02 '23 at 11:07
  • @vicegax it does not actually give any mistake nor any print out, it just does not do anything. – Pro Girl Mar 02 '23 at 11:26

2 Answers2

1

Your player variable is a computed property, this will be different every time you access it.

Try modifying your code like this:

let player: AVPlayer = {
    let player = AVPlayer(url: videoURL)
    player.play()
    return player
}()

This is just a temporal solution though, there is still the risk for the player to be generated again every time your View changes, due to SwiftUI Views life-cycle (they are value types, not reference types).

A longer term solution would be to abstract the player from the view itself, on an ObservableObject for example.

vicegax
  • 4,709
  • 28
  • 37
0

I also found this solution that works as well, but makes the code a little longer:

struct SpecialVideo5: View {
    let videoURL = Bundle.main.url(forResource: "survivor", withExtension: "mp4")!
    @Binding var path: NavigationPath
    
    @State private var player: AVPlayer?

    var body: some View {
        ZStack {
            Color(.black).ignoresSafeArea()
            VideoPlayer(player: player)
                .scaledToFill()
            HStack{
                Spacer()
                VStack {
                    NavigationLink("Bet", value: Route.linkSpecials).buttonStyle(BtnVid(vidIcon: "share"))
                    NavigationLink("Bet", value: Route.linkSpecials).buttonStyle(BtnVid(vidIcon: "hearth"))
                    Spacer()
                }.frame(maxHeight: 330).padding(.trailing, 16).padding(.top, 50)
            }
            VStack {
                Spacer()
                NavigationLink("Bet", value: Route.linkBetSurvivor).buttonStyle(BtnFull())
            }.frame(maxHeight: 330)
        }
        .navigationBarBackButtonHidden()
        .toolbar {
                ToolbarItem(placement: .navigationBarTrailing) {
                    Button {
                        path.removeLast()
                    } label: {
                        HStack(spacing: 0) {
                            Spacer()
                            Image("x")
                        }.padding(.top, 25)
                    }
                }
        }
        .onAppear {
            player = AVPlayer(url: videoURL)
            player?.play()
        }
        .onDisappear {
            player?.pause()
            player = nil
        }
    }
}
Pro Girl
  • 762
  • 7
  • 21