swiftuiswiftui-navigationlinkswiftui-ontapgesture

SWIFTUI for IOS16 Navigation link stopped working when added ".onTapGesture", how to fix?


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.


Solution

  • 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.