Jak zablokować orientację jednego kontrolera widoku w trybie portretowym tylko w Swift


103

Ponieważ moja aplikacja obsługuje wszystkie orientacje. Chciałbym zablokować tylko tryb portretowy do określonego UIViewController.

np. załóżmy, że była to aplikacja z zakładkami, a gdy widok logowania pojawia się modalnie, chcę, aby widok logowania był tylko w trybie pionowym, bez względu na to, jak użytkownik obraca urządzenie lub jak będzie aktualna orientacja urządzenia


Odpowiedzi:


271

Sytuacja może być dość skomplikowana, gdy masz skomplikowaną hierarchię widoków, na przykład wiele kontrolerów nawigacji i / lub kontrolerów widoku kart.

Ta implementacja umieszcza je na poszczególnych kontrolerach widoku, aby ustawić, kiedy chcą zablokować orientacje, zamiast polegać na delegacie aplikacji, aby znaleźć je przez iterację przez podglądy.

Swift 3, 4, 5

W AppDelegate:

/// set orientations you want to be allowed in this property by default
var orientationLock = UIInterfaceOrientationMask.all

func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
        return self.orientationLock
}

W innej globalnej klasie strukturalnej lub pomocniczej utworzyłem tutaj AppUtility:

struct AppUtility {

    static func lockOrientation(_ orientation: UIInterfaceOrientationMask) {
    
        if let delegate = UIApplication.shared.delegate as? AppDelegate {
            delegate.orientationLock = orientation
        }
    }

    /// OPTIONAL Added method to adjust lock and rotate to the desired orientation
    static func lockOrientation(_ orientation: UIInterfaceOrientationMask, andRotateTo rotateOrientation:UIInterfaceOrientation) {
   
        self.lockOrientation(orientation)
    
        UIDevice.current.setValue(rotateOrientation.rawValue, forKey: "orientation")
        UINavigationController.attemptRotationToDeviceOrientation()
    }

}

Następnie w żądanym kontrolerze ViewController, który chcesz zablokować orientacje:

 override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    
    AppUtility.lockOrientation(.portrait)
    // Or to rotate and lock
    // AppUtility.lockOrientation(.portrait, andRotateTo: .portrait)
    
}

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    
    // Don't forget to reset when view is being removed
    AppUtility.lockOrientation(.all)
}

Jeśli iPad lub aplikacja uniwersalna

Upewnij się, że opcja „Wymaga pełnego ekranu” jest zaznaczona w Ustawieniach celu -> Ogólne -> Informacje o wdrożeniu. supportedInterfaceOrientationsFordelegat nie zostanie wywołany, jeśli nie jest to zaznaczone. wprowadź opis obrazu tutaj


Wygląda na to, że to kontrola kodu ... sprawdzę, wydaje się dobra odpowiedź.
Thiha Aung

18
Po wielu szalonych badaniach jest to jedyna odpowiedź, która mi pasuje. Swift 3 - Xcode 8.2.1
Xavier Garcia Rubio

1
@pbm Kilka aplikacji w firmie Pracuję nad ustawieniami blokowania w określonych częściach w całej aplikacji i wszystkie zostały wielokrotnie zatwierdzone w sklepie z aplikacjami przez wiele lat. Mimo to nie mogę zagwarantować, że Apple nie będzie miał z tym problemu w przyszłości. Ale jak dotąd nie ma problemów i jestem pewien, że wiele aplikacji robi to w takiej czy innej formie.
bmjohns

2
Jeśli Requires full screenzaznaczysz, uniemożliwi to dostęp do aplikacji do przesuwania i dzielenia widoku. Zobacz: Stosowanie ulepszeń wielozadaniowości na iPadzie autorstwa Apple. Mam odpowiedź, która nie wymaga włączeniaRequires full screen
John Pang

2
Nie działa, drugi układ viewController nie zaktualizował jego wyświetlania tylko w orientacji pionowej.
iCoder

28

Szybki 4

wprowadź opis obrazu tutaj AppDelegate

var orientationLock = UIInterfaceOrientationMask.all

func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
    return self.orientationLock
}
struct AppUtility {
    static func lockOrientation(_ orientation: UIInterfaceOrientationMask) {
        if let delegate = UIApplication.shared.delegate as? AppDelegate {
            delegate.orientationLock = orientation
        }
    }

    static func lockOrientation(_ orientation: UIInterfaceOrientationMask, andRotateTo rotateOrientation:UIInterfaceOrientation) {
        self.lockOrientation(orientation)
        UIDevice.current.setValue(rotateOrientation.rawValue, forKey: "orientation")
    }
}

Twój ViewController Dodaj następującą linię, jeśli potrzebujesz tylko orientacji pionowej. musisz zastosować to do wszystkich ViewController, które muszą wyświetlać tryb pionowy.

override func viewWillAppear(_ animated: Bool) {
AppDelegate.AppUtility.lockOrientation(UIInterfaceOrientationMask.portrait, andRotateTo: UIInterfaceOrientation.portrait)
    }

a to spowoduje orientację ekranu dla innych Viewcontroller zgodnie z fizyczną orientacją urządzenia.

override func viewWillDisappear(_ animated: Bool) {
        AppDelegate.AppUtility.lockOrientation(UIInterfaceOrientationMask.all)

    }

W przypadku Swift 4 jest to zdecydowanie najlepsza odpowiedź. To jest dokładnie to, czego potrzebowałem, ponieważ naśladuje zachowanie aplikacji aparatu na iOS.
nocdib

@Nahid Czy zastępujemy oryginał func application w aplikacji delegata tą funkcjąfunc application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask { return self.orientationLock ?
Moondra

Po godzinie lub dwóch szukaniu rozwiązania i kilku próbach jest to rozwiązanie doskonale działające. Ustawia orientację widoku, wymusza go przy ładowaniu widoku, odblokowuje przy przechodzeniu do innego widoku, działa w nawigacji po kartach, a kod jest prosty i przejrzysty. Dziękuję @Nahid
Radek Sip

13

Swift 3 i 4

Ustaw supportedInterfaceOrientationswłaściwość określonych UIViewControllers w następujący sposób:

class MyViewController: UIViewController {

    var orientations = UIInterfaceOrientationMask.portrait //or what orientation you want
    override var supportedInterfaceOrientations : UIInterfaceOrientationMask {
    get { return self.orientations }
    set { self.orientations = newValue }
    }

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    //...
}

AKTUALIZACJA

To rozwiązanie działa tylko wtedy, gdy nieviewController jest osadzone w , ponieważ orientacja dziedziczy z elementu nadrzędnego viewController. W tym przypadku można utworzyć podklasę i ustawić w niej te właściwości.UINavigationController
UINavigationViewController


Dzięki. Działa to dobrze, ponieważ chcę ograniczyć określony widok tylko do portretu. Nie cała aplikacja.
user3204765

Wszystko, czego potrzebuję, to sterowanie określonymi kontrolerami widoku, aby zablokować orientację niezależnie od orientacji urządzenia i to działało świetnie!
Ryan B.

9

Dodaj ten kod, aby wymusić portret i zablokować go:

override func viewDidLoad() {
    super.viewDidLoad()

    // Force the device in portrait mode when the view controller gets loaded
    UIDevice.currentDevice().setValue(UIInterfaceOrientation.Portrait.rawValue, forKey: "orientation") 
}

override func shouldAutorotate() -> Bool {
    // Lock autorotate
    return false
}

override func supportedInterfaceOrientations() -> Int {

    // Only allow Portrait
    return Int(UIInterfaceOrientationMask.Portrait.rawValue)
}

override func preferredInterfaceOrientationForPresentation() -> UIInterfaceOrientation {

    // Only allow Portrait
    return UIInterfaceOrientation.Portrait
}

W AppDelegate - ustaw supportedInterfaceOrientationsForWindow na dowolne orientacje, które ma obsługiwać cała aplikacja:

func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> UIInterfaceOrientationMask {
    return UIInterfaceOrientationMask.All
} 

Dziękuję Valentin, bardzo doceniam twoją pomoc, ale twój kod nie wyszedł, a teraz rozwiązałem i odpowiedziałem na moje pytanie.
Thiha Aung

8

To jest ogólne rozwiązanie Twojego problemu i innych powiązanych problemów.

1. Utwórz pomocniczą klasę UIHelper i użyj następujących metod:

    /**This method returns top view controller in application  */
    class func topViewController() -> UIViewController?
    {
        let helper = UIHelper()
        return helper.topViewControllerWithRootViewController(rootViewController: UIApplication.shared.keyWindow?.rootViewController)
    }

    /**This is a recursive method to select the top View Controller in a app, either with TabBarController or not */
    private func topViewControllerWithRootViewController(rootViewController:UIViewController?) -> UIViewController?
    {
        if(rootViewController != nil)
        {
            // UITabBarController
            if let tabBarController = rootViewController as? UITabBarController,
                let selectedViewController = tabBarController.selectedViewController {
                return self.topViewControllerWithRootViewController(rootViewController: selectedViewController)
            }

            // UINavigationController
            if let navigationController = rootViewController as? UINavigationController ,let visibleViewController = navigationController.visibleViewController {
                return self.topViewControllerWithRootViewController(rootViewController: visibleViewController)
            }

            if ((rootViewController!.presentedViewController) != nil) {
                let presentedViewController = rootViewController!.presentedViewController;
                return self.topViewControllerWithRootViewController(rootViewController: presentedViewController!);
            }else
            {
                return rootViewController
            }
        }

        return nil
    }

2. Stwórz protokół ze swoim zachowaniem pożądania, dla twojego konkretnego przypadku będzie portret.

protokół orientacjiIsOnlyPortrait {}

Uwaga: jeśli chcesz, dodaj go na początku klasy UIHelper.

3. Rozszerz swój kontroler widoku

W Twoim przypadku:

class Any_ViewController: UIViewController,orientationIsOnlyPortrait {

   ....

}

4. W klasie delegatów aplikacji dodaj tę metodę:

 func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
        let presentedViewController = UIHelper.topViewController()
        if presentedViewController is orientationIsOnlyPortrait {
            return .portrait
        }
        return .all
    }

Uwagi końcowe:

  • Jeśli więcej klas jest w trybie portretowym, po prostu rozszerz ten protokół.
  • Jeśli chcesz, aby inne zachowania z kontrolerów widoku, utwórz inne protokoły i postępuj zgodnie z tą samą strukturą.
  • Ten przykład rozwiązuje problem ze zmianami orientacji po wypychaniu kontrolerów widoku

Podobnie jak to rozwiązanie, ale uważam, że funkcje UIHelper są bardziej przydatne jako rozszerzenia UINavigationController.
Michael Long

7

W przypadku nowej wersji Swift spróbuj tego

override var shouldAutorotate: Bool {
    return false
}

override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
    return UIInterfaceOrientationMask.portrait
}

override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
    return UIInterfaceOrientation.portrait
}

Właśnie tego potrzebowałem! Dla kontrolera iPada obowiązują wszystkie opcje orientacji, a dla kontrolera iPhone'a tylko tryb pionowy, wpisując w nim tylko te trzy zastąpienia - Idealnie.
VYT

5

Kilka świetnych odpowiedzi w tym wątku, ale żadna nie odpowiadała moim potrzebom. Mam aplikację z zakładkami z kontrolerami nawigacyjnymi na każdej karcie i jeden widok wymagał obrócenia, podczas gdy inne musiały być zablokowane w pionie. Z jakiegoś powodu kontroler nawigacji nie zmienił poprawnie rozmiaru podglądów podrzędnych. Znalazłem rozwiązanie (w Swift 3), łącząc się z odpowiedzią, a problemy z układem zniknęły. Utwórz strukturę zgodnie z sugestią @bmjohns:

import UIKit

struct OrientationLock {

    static func lock(to orientation: UIInterfaceOrientationMask) {
        if let delegate = UIApplication.shared.delegate as? AppDelegate {
            delegate.orientationLock = orientation
        }
    }

    static func lock(to orientation: UIInterfaceOrientationMask, andRotateTo rotateOrientation: UIInterfaceOrientation) {
        self.lock(to: orientation)
        UIDevice.current.setValue(rotateOrientation.rawValue, forKey: "orientation")
    }
} 

Następnie podklasa UITabBarController:

    import UIKit

class TabBarController: UITabBarController, UITabBarControllerDelegate {
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        self.delegate = self
    }

    func tabBarControllerSupportedInterfaceOrientations(_ tabBarController: UITabBarController) -> UIInterfaceOrientationMask {
        if tabBarController.selectedViewController is MyViewControllerNotInANavigationControllerThatShouldRotate {
            return .allButUpsideDown
        } else if let navController = tabBarController.selectedViewController as? UINavigationController, navController.topViewController is MyViewControllerInANavControllerThatShouldRotate {
            return .allButUpsideDown
        } else {
            //Lock view that should not be able to rotate
            return .portrait
        }
    }

    func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
        if viewController is MyViewControllerNotInANavigationControllerThatShouldRotate {
            OrientationLock.lock(to: .allButUpsideDown)
        } else if let navController = viewController as? UINavigationController, navController.topViewController is MyViewControllerInANavigationControllerThatShouldRotate {
            OrientationLock.lock(to: .allButUpsideDown)
        } else {
            //Lock orientation and rotate to desired orientation
            OrientationLock.lock(to: .portrait, andRotateTo: .portrait)
        }
        return true
    }
}

Nie zapomnij zmienić klasy TabBarController w scenorysie na nowo utworzoną podklasę.


4

Oto prosty sposób, który działa dla mnie ze Swift 4.2 (iOS 12.2), umieść to w, UIViewControllerdla którego chcesz wyłączyć shouldAutorotate:

override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
    return .portrait
}

.portraitCzęść informuje go, w którym orientacja (s) pozostanie, można zmienić to jak chcesz. Do wyboru są: .portrait, .all, .allButUpsideDown, .landscape, .landscapeLeft, .landscapeRight, .portraitUpsideDown.


2

Aby ustawić orientację poziomą dla wszystkich widoków aplikacji i zezwolić tylko na jeden widok dla wszystkich orientacji (na przykład w celu dodania rolki z aparatu):

W AppDelegate.swift:

var adaptOrientation = false

W: didFinishLaunchingWithOptions

NSNotificationCenter.defaultCenter().addObserver(self, selector: "adaptOrientationAction:", name:"adaptOrientationAction", object: nil)

W innym miejscu w AppDelegate.swift:

func application(application: UIApplication, supportedInterfaceOrientationsForWindow window: UIWindow?) -> Int {
    return checkOrientation(self.window?.rootViewController)
}

func checkOrientation(viewController:UIViewController?)-> Int{
    if (adaptOrientation == false){
        return Int(UIInterfaceOrientationMask.Landscape.rawValue)
    }else {
        return Int(UIInterfaceOrientationMask.All.rawValue)
    }
}

func adaptOrientationAction(notification: NSNotification){
    if adaptOrientation == false {
        adaptOrientation = true
    }else {
        adaptOrientation = false
    }
}

Następnie w widoku, który idzie do tego, który chcesz mieć wszystkie orientacje:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
    if (segue.identifier == "YOURSEGUE") {
        NSNotificationCenter.defaultCenter().postNotificationName("adaptOrientationAction", object: nil)
    }
}

override func viewWillAppear(animated: Bool) {
    if adaptOrientation == true {
        NSNotificationCenter.defaultCenter().postNotificationName("adaptOrientationAction", object: nil)
    }
}

Ostatnią rzeczą jest zaznaczenie Orientacja urządzenia: - Pionowa - Pozioma lewa - Pozioma prawa


2

Utwórz nowe rozszerzenie za pomocą

import UIKit

extension UINavigationController {
    override open var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        return .portrait
    }
}

extension UITabBarController {
    override open var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        return .portrait
    }
}

1

bmjohns -> Jesteś moim zbawcą życia. To jedyne działające rozwiązanie (ze strukturą AppUtility)

Stworzyłem tę klasę:

class Helper{
    struct AppUtility {

        static func lockOrientation(_ orientation: UIInterfaceOrientationMask) {

            if let delegate = UIApplication.shared.delegate as? AppDelegate {
                delegate.orientationLock = orientation
            }
        }

        /// OPTIONAL Added method to adjust lock and rotate to the desired orientation
        static func lockOrientation(_ orientation: UIInterfaceOrientationMask, andRotateTo rotateOrientation:UIInterfaceOrientation) {

            self.lockOrientation(orientation)

            UIDevice.current.setValue(rotateOrientation.rawValue, forKey: "orientation")
        }

    }
}

i postępuj zgodnie z instrukcjami, a wszystko działa idealnie dla Swift 3 -> xcode w wersji 8.2.1


1

Od iOS 10 i 11 iPad obsługuje Slide Over i Split View. Aby włączyć aplikację w widoku Slide Over i Split View, Requires full screen należy usunąć zaznaczenie. Oznacza to, że zaakceptowanej odpowiedzi nie można użyć, jeśli aplikacja chce obsługiwać Slide Over i Split View. Zobacz więcej na temat wdrażania ulepszeń wielozadaniowości firmy Apple na iPadzie tutaj .

Mam rozwiązanie, które umożliwia (1) odznaczenie Requires full screen, (2) tylko jedną funkcję do zaimplementowania appDelegate(szczególnie jeśli nie chcesz / nie możesz modyfikować kontrolerów widoku docelowego) i (3) unikanie wywołań rekurencyjnych. Nie potrzeba klasy pomocniczej ani rozszerzeń.

appDelegate.swift (Swift 4)

func application(_ application: UIApplication,
                 supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask {
    // Search for the visible view controller
    var vc = window?.rootViewController
    // Dig through tab bar and navigation, regardless their order 
    while (vc is UITabBarController) || (vc is UINavigationController) {
        if let c = vc as? UINavigationController {
            vc = c.topViewController
        } else if let c = vc as? UITabBarController {
            vc = c.selectedViewController
        }
    }
    // Look for model view controller
    while (vc?.presentedViewController) != nil {
        vc = vc!.presentedViewController
    }
    print("vc = " + (vc != nil ? String(describing: type(of: vc!)) : "nil"))
    // Final check if it's our target class.  Also make sure it isn't exiting.
    // Otherwise, system will mistakenly rotate the presentingViewController.
    if (vc is TargetViewController) && !(vc!.isBeingDismissed) {
        return [.portrait]
    }
    return [.all]
}

Edytować

@bmjohns zwrócił uwagę, że ta funkcja nie jest wywoływana na iPadzie. Zweryfikowałem i tak, nie został wywołany. Zrobiłem więc trochę więcej testów i odkryłem kilka faktów:

  1. Odznaczone, Requires full screenponieważ chcę włączyć Slide Over i Slide View na iPadzie. Wymaga aplikację do obsługi wszystkich orientacji 4 dla iPada, w Info.plist: Supported interface orientations (iPad).

Moja aplikacja działa tak samo jak Facebook: na iPhonie przez większość czasu jest zablokowana do portretu. Podczas oglądania obrazu na pełnym ekranie, umożliwia obracanie obrazu w poziomie dla lepszego widoku. Na iPadzie użytkownicy mogą obracać się do dowolnej orientacji w dowolnych kontrolerach widoku. Tak więc aplikacja wygląda ładnie, gdy iPad stoi na Smart Cover (poziomo po lewej).

  1. Aby dzwonić z iPada application(_:supportedInterfaceOrientationsFor), w Info.plist zachowaj portret tylko dla iPada. Aplikacja utraci funkcję Slide Over + Split View. Ale możesz zablokować lub odblokować orientację dla dowolnego kontrolera widoku, w jednym miejscu i bez konieczności modyfikowania klasy ViewController.

  2. Wreszcie ta funkcja jest wywoływana w cyklu życia kontrolera widoku, gdy widok jest wyświetlany / usuwany. Jeśli Twoja aplikacja będzie musiała zablokować / odblokować / zmienić orientację w innym czasie, może nie działać


Czy to działa dla iPhone'a? Chcę pokazać jeden z moich kontrolerów viewController tylko w poziomie.
iCoder

Tak. pracować dla iPhone'a. Chcę, aby jeden z moich kontrolerów widoku był wyświetlany zarówno w orientacji pionowej, jak i poziomej, a po odrzuceniu go wracam do portretu.
John Pang,

1

Rzeczywiste przetestowane rozwiązanie do tego.W moim przykładzie potrzebuję, aby cała moja aplikacja była w trybie pionowym, ale orientacja tylko jednego ekranu powinna być w trybie poziomym. Ustaw orientację pionową dla aplikacji, zaznaczając tylko tryb portretowy

Kod w AppDelegate, jak opisano powyżej.

var orientationLock = UIInterfaceOrientationMask.all

func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask 
{
  return self.orientationLock
}
struct AppUtility {  

static func lockOrientation(_ orientation: UIInterfaceOrientationMask) {
    if let delegate = UIApplication.shared.delegate as? AppDelegate {
        delegate.orientationLock = orientation
    }
}
static func lockOrientation(_ orientation: UIInterfaceOrientationMask, andRotateTo rotateOrientation:UIInterfaceOrientation) {
self.lockOrientation(orientation)     
UIDevice.current.setValue(rotateOrientation.rawValue, forKey: "orientation")
}  
}

Następnie zapisz ten kod, zanim Twój kontroler widoku w orientacji poziomej zostanie przedstawiony / push.

override func viewWillAppear(_ animated: Bool) {  
super.viewWillAppear(animated)
AppDelegate.AppUtility.lockOrientation(UIInterfaceOrientationMask.portrait, andRotateTo: UIInterfaceOrientation.portrait)
}  

Następnie zapisz ten kod w rzeczywistym kontrolerze widoku (dla widoku poziomego)

override func viewWillAppear(_ animated: Bool) {  
super.viewWillAppear(animated)
AppDelegate.AppUtility.lockOrientation(UIInterfaceOrientationMask.landscape, andRotateTo: UIInterfaceOrientation.landscape)
}  

0

Dzięki powyższej odpowiedzi @ bmjohn. Oto działająca wersja Xamarin / C # kodu tej odpowiedzi, aby zaoszczędzić innym czas transkrypcji:

AppDelegate.cs

 public UIInterfaceOrientationMask OrientationLock = UIInterfaceOrientationMask.All;
 public override UIInterfaceOrientationMask GetSupportedInterfaceOrientations(UIApplication application, UIWindow forWindow)
 {
     return this.OrientationLock;
 }

Klasa Static OrientationUtility.cs:

public static class OrientationUtility
{
    public static void LockOrientation(UIInterfaceOrientationMask orientation)
    {
        var appdelegate = (AppDelegate) UIApplication.SharedApplication.Delegate;
        if(appdelegate != null)
        {
            appdelegate.OrientationLock = orientation;
        }
    }

    public static void LockOrientation(UIInterfaceOrientationMask orientation, UIInterfaceOrientation RotateToOrientation)
    {
        LockOrientation(orientation);

        UIDevice.CurrentDevice.SetValueForKey(new NSNumber((int)RotateToOrientation), new NSString("orientation"));
    }
}

Wyświetl kontroler:

    public override void ViewDidAppear(bool animated)
    {
       base.ViewWillAppear(animated);
       OrientationUtility.LockOrientation(UIInterfaceOrientationMask.Portrait, UIInterfaceOrientation.Portrait);
    }

    public override void ViewWillDisappear(bool animated)
    {
        base.ViewWillDisappear(animated);
        OrientationUtility.LockOrientation(UIInterfaceOrientationMask.All);
    }

Nie rozumiem, jakie znaczenie ma ta odpowiedź? Ta osoba spytała szybko, a Ty dałeś w Xamarin.
Mihir Oza

0

Trochę poeksperymentowałem i udało mi się znaleźć czyste rozwiązanie tego problemu. Podejście opiera się na oznaczaniu widoku za pomocą znacznika view->

W docelowym ViewController po prostu przypisz tag do widoku głównego, jak w poniższym przykładzie kodu:

class MyViewController: BaseViewController {

  // declare unique view tag identifier
  static let ViewTag = 2105981;

  override func viewDidLoad()
  {
    super.viewDidLoad();
    // assign the value to the current root view
    self.view.tag = MyViewController.ViewTag;
  }

I na koniec w AppDelegate.swift sprawdź, czy aktualnie wyświetlany widok jest tym, który oznaczyliśmy:

func application(_ application: UIApplication, supportedInterfaceOrientationsFor window: UIWindow?) -> UIInterfaceOrientationMask
{
    if (window?.viewWithTag(DesignerController.ViewTag)) != nil {
        return .portrait;
    }
    return .all;
}

To podejście zostało przetestowane z moim symulatorem i wydaje się, że działa dobrze.

Uwaga: zaznaczony widok zostanie również znaleziony, jeśli bieżący MVC nakłada się na jakiś element podrzędny ViewController w stosie nawigacji.


0

Najlepsze rozwiązanie do blokowania i zmiany orientacji w orientacji pionowej i poziomej:

Obejrzyj ten film na YouTube:

https://m.youtube.com/watch?v=4vRrHdBowyo

Ten samouczek jest najlepszy i prosty.

lub użyj poniższego kodu:

Zobacz to zdjęcie

// 1- w drugim viewcontroller ustawiamy landscapeleft, aw pierwszym viewcontroller ustawiamy portrat:

// 2- jeśli używasz NavigationController, powinieneś dodać rozszerzenie

import UIKit

class SecondViewController: UIViewController {


    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        UIDevice.current.setValue(UIInterfaceOrientation.landscapeLeft.rawValue, forKey: "orientation")
    }

    override open var shouldAutorotate: Bool {
        return false
    }

    override open var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        return .landscapeLeft
    }

    override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
        return .landscapeLeft
    }
    
    

    override func viewDidLoad() {
        super.viewDidLoad()
    }

//write The rest of your code in here


}

//if you use NavigationController, you should add this extension

extension UINavigationController {
    override open var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        return topViewController?.supportedInterfaceOrientations ?? .allButUpsideDown
    
    }
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.