5

I am making app with Video Player in it and my whole struct is made for only portrait view, except this video player. I want to enable landscape rotation just for this view. But I've chacked lots of forums and every answere was to add some code to App Delegate, and i don't have it. What can i do then.

green8
  • 376
  • 2
  • 14

2 Answers2

5

Here's a demo for you. You can change the orientation to the one you like by calling the function changeOrientation. You can also reverse an orientation change after it's done, using the .onReceive. The .onReceive is called every time there is an orientation change, so you can reverse a orientation change that you don't like.
I know this is not optimal, but this is the best i could find without using a lot of UIKit and AppDelegate. You can use AppDelegate for a better result (i think).

import SwiftUI
import UIKit

struct ContentView: View {
    
    private let rotationChangePublisher = NotificationCenter.default
        .publisher(for: UIDevice.orientationDidChangeNotification)
    @State private var isOrientationLocked = false
    
    var body: some View {
        VStack {
            Button("Change orientation") {
                if UIDevice.current.orientation.isPortrait {
                    changeOrientation(to: .landscapeLeft)
                } else {
                    changeOrientation(to: .portrait)
                }
            }.padding()
            
            Button("Orientation is \(isOrientationLocked ? "" : "NOT ")Locked to portrait-only") {
                isOrientationLocked.toggle()
            }.padding()
        }
        .font(.system(size: 17, weight: .semibold))
        .onReceive(rotationChangePublisher) { _ in
            // This is called when there is a orientation change
            // You can set back the orientation to the one you like even
            // if the user has turned around their phone to use another
            // orientation.
            if isOrientationLocked {
                changeOrientation(to: .portrait)
            }
        }
    }
    
    func changeOrientation(to orientation: UIInterfaceOrientation) {
        // tell the app to change the orientation
        UIDevice.current.setValue(orientation.rawValue, forKey: "orientation")
        print("Changing to", orientation.isPortrait ? "Portrait" : "Landscape")
    }
}

Also, make sure you've allowed different orientations that you'd like to use, beforehand:

enter image description here

Mahdi BM
  • 1,826
  • 13
  • 16
  • 1
    Everything works perfectly but it's not quite what i was looking for. I wanted to enable rotating just in this video view. And now my whole project can do that, and everything i did wasn't prepared for landscape view. So is there anyway to disable rotating in rest view. Or just enable there. – green8 Apr 10 '21 at 19:24
  • @green8: that is easy, you have to lock your project to Portrait in Xcode project setting, and you should rotate that View 90 degree, that is it – ios coder Apr 11 '21 at 12:36
  • that could work, although that is not optimal neither. I think doing it the UIKit way is the best approach but green8 was asking for not-UIKit way so i tried my best. – Mahdi BM Apr 11 '21 at 13:20
  • @green8 if you don't know already, you can add AppDelegate to a SwiftUI app quite easily. https://www.hackingwithswift.com/quick-start/swiftui/how-to-add-an-appdelegate-to-a-swiftui-app. Don't be afraid to learn how to use AppDelegate if you dont know how to work with it, because SwiftUI can't do a bunch of things without AppDelegate and you'll probably need it going forward in your app. – Mahdi BM Apr 11 '21 at 13:21
  • 1
    @MahdiBM I actually tried that before, but i gave it one more chance and found my mistake. I did it properly and it worked!!! This is link where i found the solution for whole problem if someone would have the same problem: https://stackoverflow.com/a/59634088/14480820. Thank you for help. – green8 Apr 11 '21 at 15:44
  • This solution works but sadly it's broken in ios16 – app4g Feb 15 '23 at 23:59
0

iOS 16 (and above)

guard let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene else { return }
windowScene.requestGeometryUpdate(.iOS(interfaceOrientations: .landscape)) { error in
    // handle error
}
Sergei Volkov
  • 818
  • 8
  • 15