Reputation: 317
I've a problem with SwiftUI and AVPlayer. When i rotate the device in landscape mode, the player go in fullscreen mode, but when I rotate in portrait it not exit.
The struct for AVPlayer:
import SwiftUI
import AVKit
struct AVPlayerControllerRepresentable: UIViewControllerRepresentable {
@Binding var showFullScreen: Bool
@Binding var player: AVPlayer
func makeUIViewController(context: UIViewControllerRepresentableContext<AVPlayerControllerRepresentable>) -> AVPlayerViewController {
print("makeUIViewController->",showFullScreen)
let controller = AVPlayerViewController()
controller.player = player
controller.showsPlaybackControls = false;
chooseScreenType(controller)
return controller
}
func updateUIViewController(_ uiViewController: AVPlayerViewController , context: UIViewControllerRepresentableContext<AVPlayerControllerRepresentable>) {
print("updateUIViewController->",showFullScreen)
chooseScreenType(uiViewController)
}
private func chooseScreenType(_ controller: AVPlayerViewController) {
print("chooseScreenType", self.showFullScreen)
self.showFullScreen ? controller.enterFullScreen(animated: true) : controller.exitFullScreen(animated: true)
}
}
extension AVPlayerViewController {
func enterFullScreen(animated: Bool) {
print("Enter full screen")
perform(NSSelectorFromString("enterFullScreenAnimated:completionHandler:"), with: animated, with: nil)
}
func exitFullScreen(animated: Bool) {
print("Exit full screen")
perform(NSSelectorFromString("exitFullScreenAnimated:completionHandler:"), with: animated, with: nil)
}
}
And this is my View:
VStack{
AVPlayerControllerRepresentable(showFullScreen: $fullScreen, player: $player)
.ignoresSafeArea()
.onReceive(NotificationCenter.default.publisher(for: UIDevice.orientationDidChangeNotification)) { _ in
DispatchQueue.main.async {
print("change rotation->",UIDevice.current.orientation.rawValue)
if UIDevice.current.orientation.isLandscape {
print("landscape")
self.fullScreen = true
} else {
print("portrait")
self.fullScreen = false
}
}
}
.frame(width: 290, height: 220)
.overlay {
BoxTv()
}
.opacity(1.0)
.padding([.bottom, .top], 40)
}.onAppear(){
self.player.play();
}
Can anyone help me? When rotate device in portrait mode, the function 'exitFullScreen' not called
Upvotes: 2
Views: 946
Reputation: 257493
SwiftUI seems get lost connection with representable in this scenario... anyway it is better UIKit things to be handled within UIKit flow. Representable concept has Coordinator for such cases.
So a possible approach to fix is to move everything inside AVPlayerControllerRepresentable
.
Here is main part (tested with Xcode 13.4 / iOS 15.5):
func makeUIViewController(context: UIViewControllerRepresentableContext<AVPlayerControllerRepresentable>) -> AVPlayerViewController {
let controller = AVPlayerViewController()
controller.player = player
controller.showsPlaybackControls = false;
context.coordinator.playerController = controller
return controller
}
class Coordinator: NSObject, AVPlayerViewControllerDelegate {
weak var playerController: AVPlayerViewController? {
didSet {
playerController?.delegate = self
}
}
private var subscriber: AnyCancellable? = nil
override init() {
super.init()
subscriber = NotificationCenter.default.publisher(for: UIDevice.orientationDidChangeNotification)
.sink { [weak self] _ in
self?.rotated()
}
}
func rotated() {
if UIDevice.current.orientation.isLandscape {
self.enterFullScreen(animated: true)
} else {
self.exitFullScreen(animated: true)
}
}
//...
Upvotes: 1