iosswiftlistviewswiftuivideo-player

VideoPlayer is not playing inside ListView or ForEach


I added a video player inside ListView or ScrollView with ForEach, but it is not playing.

Note: It will only work if it is inside ScrollView but without ForEach.

import SwiftUI
import AVKit

struct Content2: View {
    var body: some View {
        ScrollView {
            ForEach(0..<1) { index in
                videoView()
            }
        }
    }
}

struct videoView: View {
    @State var player = AVPlayer()
    var body: some View {
        VideoPlayer(player: player)
            .frame(height: 300)
            .onAppear{
                player.play()
            }
            .onDisappear {
                player.pause()
            }
            .onAppear {
                if let url2 = URL(string: "https://sample-videos.com/video123/mp4/720/big_buck_bunny_720p_30mb.mp4"){
                    player = AVPlayer(url: url2)
                }
            }
    }
}

Working code:

struct VideoCampaignView3: View {
    
    @State var player = AVPlayer()
    var body: some View {
        
        ScrollView {
            //ForEach(0..<1) { index in
            VideoPlayer(player: player)                               
                .frame(height: 300)
                .onAppear{
                    player.play()
                }
                .onDisappear {
                    player.pause()
                }
                .onAppear {
                    if  let url2 = URL(string: "https://sample-videos.com/video123/mp4/720/big_buck_bunny_720p_30mb.mp4") {
                        player = AVPlayer(url: url2)
                    }
                }
        }
    }
}

Question:

It should work with ForEach inside List. It only works while no subview and ScrollView.


Solution

  • If it 'works' inside a ScrollView, it is probably a race condition (it shouldn't even work, or at least not consistently). You have a player as a state variable inside your view. You call play on it in the first onAppear view modifier, and then you replace the player with a whole new player. Just get rid of the first onAppear and add player.play() after you create the AVPlayer.

    .onAppear {
        if let url2 = URL(string: "https://sample-videos.com/video123/mp4/720/big_buck_bunny_720p_30mb.mp4") {
            player = AVPlayer(url: url2)
            player.play()
        }
    }