VMI
VMI

Reputation: 1

SwiftUI AVPlayer only working with second screen

I am trying to create a presentation feature in SwiftUI. The idea is to have slides on an iPad and present those slides in a different view on an airplay screen. I am using screenDidConnectPublisher to connect to a second screen in the following way.

ContentView()
    .onReceive(screenDidConnectPublisher, perform: screenDidConnect)

Inside ContentView, there is a view (PresentView) to present slides (images and videos). Similarly, if a screen is connected via airplay, PresentScreenView presents the current slide selected from the iPad.

The issue seems to be that if there is no screen connected, sometimes, the videos on the iPad AVPlayer don't play a video, and just show a blank screen. If I connect to a second screen, the videos play on both screens.

Any ideas?

Present View (iPad)

 ZStack {
                    if let media = mediaCacheManager.mediaCache[appModel.currentSlide] {
                        if let player = media as? AVPlayer {
                            PlayerView(player: player)
                                .aspectRatio(16 / 10, contentMode: .fit)
                                .frame(width: UIScreen.main.bounds.width * 0.8)
                                .background(Color.gray.opacity(0.2))
                                .clipShape(RoundedRectangle(cornerRadius: 40))
                                .overlay(
                                    RoundedRectangle(cornerRadius: 40)
                                        .stroke(Color.gray.opacity(0.5), lineWidth: 1)
                                )
                                .onDisappear {
                                    player.pause()
                                }
                        } else if let image = media as? Image {
                            image
                                .resizable()
                                .scaledToFit()
                                .frame(width: UIScreen.main.bounds.width * 0.8)
                                .background(Color.gray.opacity(0.2))
                                .clipShape(RoundedRectangle(cornerRadius: 40))
                                .overlay(
                                    RoundedRectangle(cornerRadius: 40)
                                        .stroke(Color.gray.opacity(0.5), lineWidth: 1)
                                )
                                .padding(.vertical, 10)
                        }
                    }
                }

PresentScreenView (Screen)

//
//  PresentScreenView.swift
//  Interactive
//
//  Created by Vikrant Gurav on 07/11/2024.
//

import SwiftUI
import AVKit

struct PresentScreenView: View {
    @EnvironmentObject private var appModel: AppModel
    @EnvironmentObject var currentPresentation: CurrentPresentation
    @EnvironmentObject var mediaCacheManager: MediaCacheManager
    
    @State var currentMedia: Image?

    var body: some View {
        if let selectedPresentation = currentPresentation.currentPresentation {
            if appModel.controlScreenSlide {
            TabView(selection: $appModel.currentSlideScreen) {
                ForEach(selectedPresentation.slides.indices, id: \.self) { index in
                    if let media = mediaCacheManager.mediaCache[index] {
                        if let player = media as? AVPlayer {
                            VideoPlayer(player: player)
                                .frame( maxHeight: .infinity)
                                .ignoresSafeArea(.all)
                        }
                    }
                }
            }
            .opacity(currentMedia == nil ? 1 : 0)
            .overlay {
                if let currentMedia {
                    currentMedia
                        .resizable()
                        .scaledToFill()
                    
                }
            }
            .ignoresSafeArea(.all)
            .task(id: appModel.currentSlideScreen, {
                let newValue = appModel.currentSlideScreen
                if mediaCacheManager.typeCache[newValue] == .image {
                    currentMedia = mediaCacheManager.mediaCache[newValue] as? Image
                } else {
                    currentMedia = nil
                }
            })
            .frame(maxWidth: .infinity , maxHeight: .infinity)
            .tabViewStyle(.page(indexDisplayMode: .never))
        }
            else {
                HStack{
                    Text("Enable Screen Control")
                        .font(.largeTitle)
                        .fontWeight(.bold)
                        .frame(maxWidth: .infinity, maxHeight: .infinity)
                }
                    .overlay {
                        if let currentMedia {
                            currentMedia
                                .resizable()
                                .scaledToFill()
                            
                        }
                    }
                    .ignoresSafeArea(.all)
                    .frame(maxWidth: .infinity , maxHeight: .infinity)
            }
                }
    }
}

Upvotes: 0

Views: 27

Answers (0)

Related Questions