I have the following situation (this is just a demo application with that functionality). I have a screen with a single button (navigation link) where only portrait mode is allowed. When I click the button I remove the restrictions and it can rotate to all 4 sides. When testing on iOS 16 after going back to the first screen I again restrict it to portrait only and it force rotates when it in landscape. When done on iOS 15 it gets locked on portrait but it doesn't force rotate itself. I have to rotate for it to become portrait and fix itself there. In other words if it is in landscape -> I click back -> screen stays in landscape -> I rotate it to portrait -> it get fixated there. I want to skip the part where it stays in landscape and make it work like this in iOS 16.
@main
struct AppTesting: App {
    @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
    var body: some Scene {
        WindowGroup {
            NavigationView {
                FirstView()
                    .navigationViewStyle(.stack)
                    .navigationBarBackButtonHidden(true)
            }
        }
    }
}
class ViewModel: ObservableObject {
    @Published var isInFullScreen = false
    var cancellable: AnyCancellable?
    
    init() {
        cancellable = $isInFullScreen
            .sink { status in
                if status {
                    AppDelegate.preferredOrientation = UIDevice.current.userInterfaceIdiom == .phone ? .allButUpsideDown : .all
                    AppDelegate.unlockOrientation()
                } else {
                    AppDelegate.lockOrientation(to: .portrait)
                }
            }
    }
}
struct FirstView: View {
    @StateObject var vm = ViewModel()
    
    var body: some View {
        VStack {
            NavigationLink(isActive: $vm.isInFullScreen) {
                SecondView(vm: vm)
            } label: {
                Text("Play video in full screen")
            }
        }
    }
}
struct SecondView: View {
    @ObservedObject var vm: ViewModel
    @Environment(\.dismiss) var dismiss
    
    var body: some View {
        Button("Video Player View") {
            withAnimation {
                vm.isInFullScreen.toggle()
                self.dismiss()
            }
        }
        .navigationBarHidden(true)
    }
}
class AppDelegate: NSObject, UIApplicationDelegate {
    static var orientationLock: UIInterfaceOrientationMask?
    static var preferredOrientation: UIInterfaceOrientationMask = .portrait
    func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
        return Self.orientationLock ?? Self.preferredOrientation
    }
    
    static func lockOrientation(to orientation: UIInterfaceOrientationMask) {
        orientationLock = orientation
        if #available(iOS 16, *) {
            if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene,
               var topController = windowScene.windows.first?.rootViewController {
                while let presentedViewController = topController.presentedViewController {
                    topController = presentedViewController
                }
                topController.setNeedsUpdateOfSupportedInterfaceOrientations()
            }
        } else {
            UIViewController.attemptRotationToDeviceOrientation()
        }
    }
    
    static func unlockOrientation() {
        Self.orientationLock = nil
    }
}
I tried using the setValue method from UIDevice but I read its bad practice and Apple doesn't recommend it. Also it did break my UI.
One thing I spotted is that on iOS 16 after going back to first screen and when method setNeedsUpdateOfSupportedInterfaceOrientations() is called the then AppDelegate calls application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask which is not happenning on iOS 15. There after lockOrientation AppDelegate doesn't respond.
 
    