AVPLayer in Swiftui resets when button is pressed

Viewed 124

I have a video player and below it I have text for a title. When you tap on the text I have it increase in Font size. But when you increase the font size it causes the video to stop playing and restart. I don't want that to happen. I want the video to play unaffected by the font increase. I'm very new to swiftUI fyi.

import SwiftUI

import AVKit

struct TEST: View {

@State private var tapped: Bool = false
@State private var draggedOffset = CGSize.zero
@State private var fontSize: CGFloat = 20 // Change Font Size

var body: some View {
    
    VStack {
        
        VideoPlayer(player: AVPlayer(url: URL(string: "http://www.unisonprinting.com/0celot/dune/dune.mp4")!))
            .aspectRatio(3/2, contentMode: .fit)
        
        Text ("VIDEO TITLE")
            .foregroundColor(.white)
            .font(.system(size: fontSize))
            .onTapGesture {
                if self.fontSize < 44 {
                    self.fontSize = self.fontSize + 12
                } else {
                    self.fontSize = 20
                }
            }
    }//V

}

}

1 Answers

Right now, each the the View's body is rendered, a new AVPlayer is created, causing the video to stop playing and restart.

You can avoid this by storing the AVPlayer in a @State variable, which persists across renders:

struct TEST: View {
    
    @State private var tapped: Bool = false
    @State private var draggedOffset = CGSize.zero
    @State private var fontSize: CGFloat = 20 // Change Font Size
    
    @State private var player = AVPlayer(url: URL(string: "https://www.unisonprinting.com/0celot/dune/dune.mp4")!)
    
    var body: some View {
        
        VStack {
            
            VideoPlayer(player: player)
                .aspectRatio(3/2, contentMode: .fit)
            
            Text ("VIDEO TITLE")
                .foregroundColor(.blue)
                .font(.system(size: fontSize))
                .onTapGesture {
                    if self.fontSize < 44 {
                        self.fontSize = self.fontSize + 12
                    } else {
                        self.fontSize = 20
                    }
                }
        }
    }
}


Update, based on comments, showing one possible solution of how to have the VideoPlayer load a different AVPlayer based on a changing URL parameter:

struct ContentView: View {
    
    var url : String = "https://www.unisonprinting.com/0celot/dune/dune.mp4"
    
    @State private var tapped: Bool = false
    @State private var draggedOffset = CGSize.zero
    @State private var fontSize: CGFloat = 20 // Change Font Size
    
    @State private var player : AVPlayer?
    
    var body: some View {
        
        VStack {
            if let player = player {
                VideoPlayer(player: player)
                    .aspectRatio(3/2, contentMode: .fit)
            }
            
            Text ("VIDEO TITLE")
                .foregroundColor(.blue)
                .font(.system(size: fontSize))
                .onTapGesture {
                    if self.fontSize < 44 {
                        self.fontSize = self.fontSize + 12
                    } else {
                        self.fontSize = 20
                    }
                }
        }
        .onAppear {
            setPlayerToUrl(url)
        }
        .onChange(of: url) { url in
            setPlayerToUrl(url)
        }
    }
    
    func setPlayerToUrl(_ url: String) {
        player = AVPlayer(url: URL(string: url)!)
    }
}
Related