2

I am using SWIFTUI for iOS 16 project, I have 2 view:

  • ContentView (It has inside a regular NavigationStack with path binding)
  • TeaserView (It a full screen video that I want it to autoplay the moment the view is called) Everything works as it supposed to, till I bind the path from the ContentView inside the Teaser view, at which point for unknown reason the autoplay stops working.

How to fix so to keep the autoplay?

Here is the ContentView:

import SwiftUI

struct ContentView: View {

@State private var path = NavigationPath()

    var body: some View {

        NavigationStack(path: $path) {

            NavigationLink("Play Me", value: "")
                .navigationDestination(for: String.self) {
                    txtValue in Teaser(path: $path)
                }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

This is the TeaserView:

import SwiftUI
import AVKit

struct Teaser: View {
    
    let videoURL = URL(string:"https://SomeURLwithIntroVideo.mp4")!
    
    @Binding var path: NavigationPath
    
    var body: some View {
    
        let player = AVPlayer(url: videoURL)
        
        ZStack {
            VideoPlayer(player: player).scaledToFill().onAppear() {player.play()}
        }
        
        .navigationBarBackButtonHidden()
        .toolbar {
            ToolbarItem(placement: .navigationBarLeading) {
                Button {
                    path.removeLast()
                } label: {
                    Text("custom-btn")
                }
            }
        }
    }
}

struct Teaser_Previews: PreviewProvider {
    static var previews: some View {
        Teaser(path: .constant(NavigationPath()))
    }
}

Any suggestion on how to fix?

Pro Girl
  • 762
  • 7
  • 21

1 Answers1

1

I found a solution that works great. In the TeaserView (the video page) instead of just creating the player variable with let, create a var that starts the autoplay and most importantly returns you the player variable results, and then slide them back in the view. I know it sounds redundant, almost like making the same thing twice, but it works as well as keeping the @Binding intact and no error thrown, like so:

Replace:

let player = AVPlayer(url: videoURL)

with:

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

So at the end the new TeaserView will be:

import SwiftUI
import AVKit


struct Teaser: View {
    let videoURL = URL(string: "https://someurlblablabla.mp4")!
    
    @Binding var path: NavigationPath
    
    var player: AVPlayer {
        let player = AVPlayer(url: videoURL)
        player.play()
        return player
    }
    
    var body: some View {
        ZStack {
            Color("db").ignoresSafeArea()
            VideoPlayer(player: player)
                .scaledToFill()
        }
        .navigationBarBackButtonHidden()
        .toolbar {
            ToolbarItem(placement: .navigationBarLeading) {
                Button {
                    path.removeLast()
                } label: {
                    Text("custom-btn")
                }
            }
        }
    }
}

You don't need to do any modification to the ContentView, and you are now also free to customize the back button as you like.

Please if anyone else finds some better or shorter solution for this for iOS16 and the new NavigationStack standards, please post it.

Thanks.

Pro Girl
  • 762
  • 7
  • 21
  • 1
    If `Teaser` were ever to get recalculated, this would create new `AVPlayer`. Did you consider storing the `AVPlayer` in a `@State` variable and using `onAppear` to play it? – jnpdx Feb 20 '23 at 22:21
  • @jnpdx I did not consider that actually. In my original code I used the onAppear like so: VideoPlayer(player: player).scaledToFill().onAppear() {player.play()} however it was clashing with the $Binding, how do you suggest storing the AVPlayer in a @ State with the url? – Pro Girl Feb 20 '23 at 22:37
  • 1
    See https://stackoverflow.com/questions/56691630/swiftui-state-var-initialization-issue for how to set `@State` in `init` – jnpdx Feb 21 '23 at 19:54