iOS 6: Jak ograniczyć niektóre widoki do portretu i pozwolić innym na obracanie?

99

Mam aplikację na iPhone'a, która używa a UINavigationControllerdo prezentowania interfejsu szczegółowego: najpierw jeden widok, potem drugi, aż do czterech poziomów głębokości. Chcę, aby pierwsze trzy widoki były ograniczone do orientacji pionowej i tylko ostatni widok powinien mieć możliwość obrócenia do poziomu. Wracając z czwartego widoku do trzeciego, a czwarty widok był w orientacji poziomej, chcę, aby wszystko wróciło do pionu.

W iOS 5 po prostu zdefiniowałem shouldAutorotateToInterfaceOrientation:w każdym z moich kontrolerów widoku, aby zwracać TAK dla dopuszczalnych orientacji. Wszystko działało zgodnie z opisem powyżej, w tym powrót do portretu, nawet jeśli urządzenie było trzymane w orientacji poziomej podczas powrotu z kontrolera widoku # 4 do # 3.

W iOS 6 wszystkie kontrolery widoku obracają się do poziomu, łamiąc te, które nie były przeznaczone. W informacjach o wydaniu iOS 6 jest napisane

Większa odpowiedzialność przenosi się na aplikację i jej delegata. Teraz kontenery iOS (takie jak UINavigationController) nie konsultują się ze swoimi dziećmi w celu ustalenia, czy powinny one wykonywać autorotowanie. [...] System pyta najwyżej położony kontroler widoku pełnoekranowego (zwykle kontroler widoku głównego) o obsługiwane orientacje interfejsu za każdym razem, gdy urządzenie się obraca lub gdy kontroler widoku jest prezentowany w trybie prezentacji pełnoekranowej. Ponadto obsługiwane orientacje są pobierane tylko wtedy, gdy ten kontroler widoku zwraca wartość YES ze swojej shouldAutorotatemetody. [...] System określa, czy orientacja jest obsługiwana przez przecięcie wartości zwracanej przez supportedInterfaceOrientationsForWindow:metodę aplikacji z wartością zwracaną przez supportedInterfaceOrientationsmetodę najwyższego pełnoekranowego kontrolera.

Więc podklasowałem UINavigationController, nadałem mojej MainNavigationControllerwłaściwości boolowskiej landscapeOKi użyłem tego do zwrócenia dopuszczalnych orientacji w supportedInterfaceOrientations. Następnie w każdej z viewWillAppear:metod kontrolerów widoku mam taką linię

    [(MainNavigationController*)[self navigationController] setLandscapeOK:YES];

powiedzieć mojemu MainNavigationControllerpożądanemu zachowaniu.

Pojawia się pytanie: jeśli teraz przejdę do mojego czwartego widoku w trybie portretowym i obrócę telefon, obróci się on do poziomu. Teraz naciskam przycisk Wstecz, aby wrócić do mojego trzeciego widoku, który powinien być tylko portretem. Ale nie obraca się z powrotem. Jak mam to zrobić?

próbowałem

    [[UIApplication sharedApplication] setStatusBarOrientation:UIInterfaceOrientationPortrait]

w viewWillAppearmetodzie mojego trzeciego kontrolera widoku, ale nic nie robi. Czy to niewłaściwa metoda wywołania, czy może niewłaściwe miejsce, aby to wywołać, czy też powinienem zaimplementować całość w zupełnie inny sposób?

Harald Bögeholz
źródło

Odpowiedzi:

95

Miałem ten sam problem i znalazłem rozwiązanie, które działa dla mnie. Aby to zadziałało, nie wystarczy zaimplementować - (NSUInteger)supportedInterfaceOrientationsw UINavigationController. Musisz również zaimplementować tę metodę w kontrolerze # 3, który jest pierwszym, który ma być tylko portretowy po wystrzeleniu kontrolera # 4. Tak więc mam następujący kod w moim UINavigationController:

- (BOOL)shouldAutorotate
{
    return YES;
}

- (NSUInteger)supportedInterfaceOrientations
{
    if (self.isLandscapeOK) {
        // for iPhone, you could also return UIInterfaceOrientationMaskAllButUpsideDown
        return UIInterfaceOrientationMaskAll;
    }
    return UIInterfaceOrientationMaskPortrait;
}

W widoku kontrolera nr 3 dodaj następujące elementy:

- (NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait;
}

Nie musisz niczego dodawać do swoich kontrolerów widoku nr 1, 2 i 4. To działa dla mnie, mam nadzieję, że ci pomoże.

Flo
źródło
8
rozwiązałeś coś, co ludzie próbowali rozwiązać od miesięcy! zasługujesz za to na wielkie uznanie! Dodałem obsługiwaneInterfaceOrientations do kategorii na UIViewController i działa to doskonale jako domyślne dla tych kontrolerów tylko do portretu.
dwery
3
Spośród 100 różnych odpowiedzi na SO, ta naprawdę działa. Dzięki :-)
Christer Nordvik
16
Mam to skonfigurowane i nadal mam złą orientację, gdy wracam z trybu pionowego do kontrolera widoku ograniczonego tylko do krajobrazu. Nie przechodzi automatycznie do krajobrazu - czy ktoś jeszcze go widzi?
Oded Ben Dov
1
co się stanie, jeśli żądany kontroler widoku krajobrazu jest prezentowany z płynnej ścieżki i nie ma kontrolera nawigacji?
jesses.co.tt
1
Edytuj ostatnią, tak aby była NSUInteger jako typ zwracany.
nieobecny
68

Dodaj CustomNavigationController

Zastąp w nim te metody:

-(BOOL)shouldAutorotate
{
    return [[self.viewControllers lastObject] shouldAutorotate];
}

-(NSUInteger)supportedInterfaceOrientations
{
    return [[self.viewControllers lastObject] supportedInterfaceOrientations];
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation
{
    return [[self.viewControllers lastObject] preferredInterfaceOrientationForPresentation];
}

Teraz dodaj wszystkie orientacje na liście

wprowadź opis obrazu tutaj

W kontrolerze widoku dodaj tylko te wymagane:

-(BOOL)shouldAutorotate
{
    return YES;
}

-(NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait;
}

te metody zastępują metody kontrolera nawigacji

Zaraki
źródło
5
Tą odpowiedzią naprawdę się udało! Dziękuję bardzo. Naprawdę bardzo pomogłeś. To był dla mnie duży problem przez jakiś czas. Dobra robota.
K2Digital,
Dziękuję Ci! Zajęło mi to tyle czasu i energii, żeby się tego dowiedzieć!
bkbeachlabs
Oszczędzasz życie ... Działa to również w mojej aplikacji. Właściwie to, co chcę w mojej aplikacji, to wszystko, co mam ViewControllerw trybie portretowym, a mój ViewControllerjest w trybie krajobrazu i portretu. Daję również wsparcie zarówno w iOS 5.0, jak i iOS 6.0.Dlatego jestem zdezorientowany, ale to świetne rozwiązanie. dodaję CustomNavigationController do mojego głównego kontrolera widoku i udzielam wsparcia zgodnie z moimi potrzebami. Jeszcze raz dziękuję.
Bhavin_m
Fantastyczny. Dokładnie to, czego potrzebowałem. Dziękuję Ci.
mszaro,
co się stanie, jeśli żądany kontroler widoku krajobrazu jest prezentowany z płynnej ścieżki i nie ma kontrolera nawigacji?
jesses.co.tt
9

Po przejrzeniu każdej odpowiedzi w niezliczonych podobnych pytaniach dotyczących SO, żadna z odpowiedzi nie działała dla mnie, ale dali mi kilka pomysłów. Oto, jak ostatecznie rozwiązałem problem:

Najpierw upewnij się, że Obsługiwane orientacje interfejsu w miejscu docelowym projektu zawierają wszystkie orientacje, które chcesz dla widoku obrotowego.

wprowadź opis obrazu tutaj

Następnie utwórz kategorię UINavigationController(ponieważ Apple mówi, aby nie tworzyć podklasy):

@implementation UINavigationController (iOS6AutorotationFix)

-(BOOL)shouldAutorotate {
    return [self.topViewController shouldAutorotate];
}

@end

Zaimportuj tę kategorię i kontroler widoku, który chcesz mieć możliwość obracania (który będę wywoływać RotatingViewController) do kontrolera widoku najwyższego poziomu, który powinien zawierać kontroler nawigacji. W tym widoku kontroler zaimplementuj shouldAutorotatew następujący sposób. Zwróć uwagę, że nie powinien to być ten sam kontroler widoku, który chcesz obrócić.

-(BOOL)shouldAutorotate {

    BOOL shouldRotate = NO;

    if ([navigationController.topViewController isMemberOfClass:[RotatingViewController class]] ) {
        shouldRotate = [navigationController.topViewController shouldAutorotate];
    }

    return shouldRotate;
}

Wreszcie w swoim RotatingViewController, zaimplementuj shouldAutorotatei supportedInterfaceOrientationsw następujący sposób:

-(BOOL)shouldAutorotate {
    // Preparations to rotate view go here
    return YES;
}

-(NSUInteger)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskAllButUpsideDown; // or however you want to rotate
}

Powodem, dla którego musisz to zrobić, jest to, że iOS 6 daje kontrolę nad obrotem do głównego kontrolera widoku zamiast kontrolera widoku z góry. Jeśli chcesz, aby obrót pojedynczego widoku zachowywał się inaczej niż inne widoki w stosie, musisz napisać dla niego konkretny przypadek w głównym kontrolerze widoku.

Brian
źródło
2
To doskonała odpowiedź, która zasługuje na więcej miłości. Oto część informacji, które zawiera, których nie mogłem znaleźć nigdzie indziej i która jest krytyczna: jeśli chcesz, aby rotacja pojedynczego widoku zachowywała się inaczej niż inne widoki w stosie, musisz napisać dla niego konkretny przypadek w katalogu głównym kontroler widoku
shmim
Przypuszczam, że to zadziała, jeśli jako pierwszy element członkowski storyboardu aplikacji jako kontroler początkowy masz NavigationController, ale co w przypadku, gdy początkowy kontroler jest po prostu ViewController?
Duck
4

Nie mam wystarczającej reputacji, aby skomentować odpowiedź @ Briana, więc dodam tutaj swoją notatkę.

Brian wspomniał, że iOS6 daje kontrolę rotacji do rootViewController - może to być nie tylko UINavigationController, jak wspomniano, ale także UITabBarController, którym był dla mnie. Moja struktura wygląda tak:

  • UITabBarController
    • UINavigationController
      • UIViewControllers ...
    • UINavigationController
      • UIViewControllers ...

Dlatego dodałem metody najpierw w niestandardowym UITabBarController, następnie w niestandardowym UINavigationController, a na końcu w określonym UIViewController.

Przykład z UITabBarController i UINavigationController:

- (BOOL)shouldAutorotate {
    return [self.viewControllers.lastObject shouldAutorotate];
}

- (NSUInteger)supportedInterfaceOrientations {
    return [self.viewControllers.lastObject supportedInterfaceOrientations];
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
    return [self.viewControllers.lastObject shouldAutorotateToInterfaceOrientation:toInterfaceOrientation];
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
    return [self.viewControllers.lastObject preferredInterfaceOrientationForPresentation];
}
micmdk
źródło
Właściwie użyłem UITabBarController jako zmiennej instancji w moim głównym kontrolerze widoku, ponieważ nie powinno się tworzyć podklasy UITabBarController w wersjach iOS wcześniejszych niż 6.0 i potrzebowałem obsługiwać z powrotem do iOS 5.0.
Brian
@micmdk Mam ten sam problem. proszę doradzić, jak rozwiązać ten problem, skopiowałem Twój kod i umieściłem go w niestandardowym kontrolerze nawigacji i niestandardowym kontrolerze UabbarController oraz ustawiłem inny kontroler widoku jako przewodnik Briana. ale nadal nie mam naprawionego kontrolera widoku w pionie.
Ram S
@Brian Mam ten sam problem. proszę doradzić, jak rozwiązać ten problem, skopiowałem Twój kod i umieściłem go w niestandardowym kontrolerze nawigacji i niestandardowym kontrolerze UabbarController oraz ustawiłem inny kontroler widoku jako prowadzony przez Micmdk. ale nadal nie otrzymuję poprawionego kontrolera widoku w portrecie w ios8.
Ram S
3

Chciałbym udzielić częściowej odpowiedzi na moje własne pytanie. Znalazłem następujący wiersz kodu, użyty w viewWillAppearmetodzie mojej trzeciej UIViewController, działa:

[[UIDevice currentDevice] 
      performSelector:NSSelectorFromString(@"setOrientation:") 
           withObject:(id)UIInterfaceOrientationPortrait];

Ale nie podoba mi się to rozwiązanie. Wykorzystuje sztuczkę, aby przypisać właściwość tylko do odczytu, która zgodnie z dokumentacją Apple reprezentuje fizyczną orientację urządzenia. To tak, jakby powiedzieć iPhone'owi, aby przeskoczył do właściwej orientacji w dłoni użytkownika.

Kusi mnie, aby zostawić to w mojej aplikacji, ponieważ po prostu działa. Ale nie wydaje się to właściwe, więc chciałbym pozostawić pytanie otwarte, aby uzyskać czyste rozwiązanie.

Harald Bögeholz
źródło
4
Twoja aplikacja zostanie najprawdopodobniej odrzucona, jeśli ją tam zostawisz. Ja też szukam rozwiązania tego problemu, ale wygląda na to, że nie jest to możliwe. Wszystko, co udało mi się znaleźć, to odpowiedź na to pytanie: stackoverflow.com/questions/7196300/ ... to trochę działa, ale z jakiegoś powodu psuje obsługę przycisku dotykowego w jednym z moich kontrolerów widoku
Lope
Zaryzykowałem i zgłosiłem się do Apple. Wciąż czekam na recenzję ... Będę Cię informować.
Harald Bögeholz
Apple właśnie zatwierdziło moją aplikację z tym hackiem, yey! Mam nadzieję, że nie przyniesie mi to odwrotu w przyszłej aktualizacji iOS. W międzyczasie nadal jestem otwarty na sugestie dotyczące czystego rozwiązania!
Harald Bögeholz
1
@ HaraldBögeholz Grt suggetion. ale kiedy pracuję w nowym xCode z ARC, nie mogę używać ans. Otrzymuję komunikat „Cast of NSInteger (aka int) to id is niedozwolone z ARC PerformSelector może spowodować wyciek, ponieważ jego selektor jest nieznany”. Jak mogę to rozwiązać? jestem naprawdę wdzięczny, jeśli mamy rozwiązanie. Kiedy wyłączam ARC dla widoku pionowego, następuje awaria aplikacji z powodu niektórych wycieków danych. Proszę
zasugeruj
4
Korzystanie z prywatnego interfejsu API NIGDY nie jest rozwiązaniem.
Javier Soto,
2

To jest, którego używam do obsługi orientacji w iOS 6.0

-(BOOL)shouldAutorotate{
    return YES;
}  

 - (NSUInteger)supportedInterfaceOrientations{
    return UIInterfaceOrientationMaskAll;
}


- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{  
  return UIInterfaceOrientationPortrait;
}
ASHISHT
źródło
1

Ponieważ jest to bardzo popularny wątek. Pomyślałem, że dodam to, co uważam za najłatwiejszą odpowiedź. Działa to dla ios8 i nowszych

-(BOOL)shouldAutorotate
{
    return YES;
}

i

-(UIInterfaceOrientationMask)supportedInterfaceOrientations{
return UIInterfaceOrientationMaskPortrait;
}

Otóż ​​to. Cieszyć się!

Aha, i moje ViewControllery są osadzone w kontrolerze nawigacji, którego nie musiałem w żaden sposób tworzyć podklasy ani konfigurować.

Reeder32
źródło
0

To może nie działać dla wszystkich, ale dla mnie działa świetnie. Zamiast wdrażać ...

[(MainNavigationController*)[self navigationController] setLandscapeOK:YES];

in viewWillAppear we wszystkich moich kontrolerach, postanowiłem scentralizować ten proces w mojej podklasie UINavigationController, zastępując metodę UINavigationControllerDelegatenavigationController:willShowViewController:animated:

- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {

    self.previousVCLandscapeOK = self.isLandscapeOK; // Store the current VC's orientation preference before pushing on the new VC so we can set this again from within the custom "back" method
    self.isLandscapeOK = NO; // Set NO as default for all VC's
    if ([viewController isKindOfClass:[YourViewController class]]) {
        self.isLandscapeOK = YES;
    }
}

Zauważyłem, że ta metoda delegata nie jest wywoływana podczas zdejmowania VC ze stosu nawigacyjnego. Nie stanowiło to dla mnie problemu, ponieważ obsługuję funkcję wsteczną z mojej podklasy UINavigationController, dzięki czemu mogę ustawić odpowiednie przyciski paska nawigacji i działania dla określonych VC, takich jak ten ...

if ([viewController isKindOfClass:[ShareViewController class]]) {

    UIButton* backButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 57, 30)];
    [backButton setImage:[UIImage imageNamed:@"back-arrow"] forState:UIControlStateNormal];
    [backButton addTarget:self action:@selector(back) forControlEvents:UIControlEventTouchUpInside];
    UIBarButtonItem* backButtonItem = [[UIBarButtonItem alloc] initWithCustomView:backButton];
    viewController.navigationItem.leftBarButtonItem = backButtonItem;

    UIImageView* shareTitle = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"share-title"]];
    [shareTitle setContentMode:UIViewContentModeScaleAspectFit];
    [shareTitle setFrame:CGRectMake(0, 0, shareTitle.frame.size.width - 10, shareTitle.frame.size.height - 10)];
    viewController.navigationItem.titleView = shareTitle;

} else if(...) {
    ...
}

Oto, backjak wygląda moja metoda, aby obsłużyć zdejmowanie VC ze stosu i ustawić odpowiednią preferencję rotacji ...

- (void)back {
    self.isLandscapeOK = self.previousVCLandscapeOK;
    self.previousVCLandscapeOK = NO;
    [self popViewControllerAnimated:YES];
}

Tak więc, jak widać, w zasadzie wszystko, co się dzieje, to najpierw ustawiam dwie właściwości ...

@property (nonatomic) BOOL isLandscapeOK;
@property (nonatomic) BOOL previousVCLandscapeOK;

w navigationController:willShowViewController:animated:którym określi obsługiwane orientacje w ramach tego VC, który ma zostać przedstawiony. Podczas wyskakiwania VC wywoływana jest moja niestandardowa metoda „wstecz”, a następnie ustawiam isLcapesOK na to, co zostało zapisane za pomocą poprzedniej wartości VCLcapesOK.

Jak powiedziałem, może to nie działać dla wszystkich, ale działa świetnie i nie muszę się martwić o dodanie kodu do każdego z moich kontrolerów widoku, udało mi się to wszystko scentralizować w podklasie UINavigationController.

Mam nadzieję, że to komuś pomoże, tak jak mnie. Dzięki, Jeremy.

Jeremy Fox
źródło
0

Przejdź do pliku Info.plist i wprowadź zmianęwprowadź opis obrazu tutaj

Nekelle Latoya Celestine
źródło
0

Chcesz wymusić portret aplikacji iOS 6 tylko wtedy możesz dodać poniższe metody do podklasy UIViewController

- (BOOL)shouldAutorotate {
    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
        return YES;
    } else {
        return NO;
    }
}


- (NSUInteger)supportedInterfaceOrientations {
    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) {
        return UIInterfaceOrientationMaskAll;
    } else {
        return UIInterfaceOrientationMaskPortrait;
    }
}
Vaibhav Saran
źródło
2
Problem polega na tym, że jeśli ten widok nie jest widokiem głównym (czego nie ma w tym pytaniu), shouldAutorotate nie zostanie wywołana.
Brian
z jakiegokolwiek powodu return type NSUIntegergeneruje ostrzeżenie, mimo że jest to poprawny typ var. jeśli masz OCD, użyj UIInterfaceOrientationMaskzamiast tego.
Chris J
Również to rozwiązanie działało doskonale dla kontrolera widoku modalnego (widok z kamery), który mam, bez potrzeby tworzenia podklasy UINavigationController. Domyślam się, że modale są traktowane niezależnie. Nie dotyczy pierwotnego pytania, ale przydatne informacje do projektowania.
Chris J
0

Chciałem, aby wszystkie moje VC były zablokowane w orientacji pionowej z wyjątkiem jednego. To mi się udało.

  1. Dodaj obsługę wszystkich orientacji w pliku plist.
  2. W głównym kontrolerze widoku wykryj rodzaj kontrolera widoku, który znajduje się w górnej części okna, i odpowiednio ustaw orientację aplikacji w metodzie supportedInterfaceOrientations . Na przykład potrzebowałem, aby moja aplikacja obracała się tylko wtedy, gdy widok sieciowy znajdował się na szczycie stosu. Oto, co dodałem w moim rootVC:

    -(NSUInteger)supportedInterfaceOrientations
    {
        UIViewController *topMostViewController = [[Utils getAppDelegate] appNavigationController].topViewController;
        if ([topMostViewController isKindOfClass:[SVWebViewController class]]) {
            return UIInterfaceOrientationMaskAllButUpsideDown;
        }
        return UIInterfaceOrientationMaskPortrait;
    }
Trunal Bhanse
źródło
Trunal, to jest kilka miesięcy, ale czy możesz podać trochę więcej szczegółów na temat wykrywania rodzaju kontrolera widoku, który jest na górze. W szczególności nie jestem pewien, co tu robisz [[Utils getAppDelegate] appNavigationController]. Narzędzia Myślę, że to jakaś klasa, którą masz, ale nie wiem, co w niej robisz. Każda pomoc byłaby świetna!
Ben
0

Nie mam wystarczającej reputacji, aby odpowiedzieć na pytanie @Ram S pod odpowiedzią @micmdk, więc dodam tutaj swoją notatkę.

Kiedy używasz UITabbarController , spróbuj zmienić self.viewControllers.lastObject w kodzie @ micmdk na self.selectedViewController w następujący sposób:

- (BOOL)shouldAutorotate {
    return [self.selectedViewController shouldAutorotate];
}

- (NSUInteger)supportedInterfaceOrientations {
    return [self.selectedViewController supportedInterfaceOrientations];
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation {
    return [self.selectedViewController shouldAutorotateToInterfaceOrientation:toInterfaceOrientation];
}

- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
    return [self.selectedViewController preferredInterfaceOrientationForPresentation];
}
phantom_2
źródło
0

Możesz implementować i przesłonić shouldAutorotate () i obsługiwaneInterfaceOrientations var we wszystkich klasach kontrolera widoku, które powinny być prezentowane w innych orientacjach niż te zdefiniowane w PLIŚCIE Twojej aplikacji.

Jednak w nietrywialnym interfejsie użytkownika możesz napotkać problem z dodaniem go do dziesiątek klas i nie chcesz, aby wszystkie były podklasą kilku wspólnych, które go obsługują (MyBaseTableViewController, MyBaseNavigationController i MyBaseTabBarController).

Ponieważ nie można zastąpić tej metody / var bezpośrednio w UIViewController, możesz to zrobić na jego podklasach, które są zwykle twoimi klasami podstawowymi, takimi jak UITableViewController, UINavigationController i UITabBarController.

Możesz więc zaimplementować kilka rozszerzeń i nadal skonfigurować MyPreciousViewController, aby wyświetlał się w innych orientacjach niż wszystkie inne, takie jak ten fragment kodu Swift 4:

extension UITableViewController {
    override open var supportedInterfaceOrientations: UIInterfaceOrientationMask {

    if let last = self.navigationController?.childViewControllers.last,
        last != self {
            return last.supportedInterfaceOrientations
    } else {
        return [.portrait]
    }
    }
}

extension MyPreciousViewController {
    override open var supportedInterfaceOrientations: UIInterfaceOrientationMask {

    return [.portrait,.landscape]
    }
}


extension UINavigationController {
    override open var supportedInterfaceOrientations: UIInterfaceOrientationMask {

        return [.portrait]
    }
}


extension UITabBarController {
    override open var supportedInterfaceOrientations: UIInterfaceOrientationMask {

        return [.portrait]
    }
}
vedrano
źródło
0

Rozwiązałem ten sam problem.

Jeśli używasz do UINavigationControllerprzekazywania kontrolerów widoku, musisz ustawić poniższe metody.

extension UINavigationController{

    override open var shouldAutorotate: Bool {

        if topViewController != nil && (topViewController?.isKind(of: LogInViewController.self))!
        {
            return true
        }
        return false
    }

    override open var supportedInterfaceOrientations: UIInterfaceOrientationMask {

        if topViewController != nil && (topViewController?.isKind(of: LogInViewController.self))!
        {
            return .portrait
        }
        return .landscapeRight

    }
    override open var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {

        if topViewController != nil && (topViewController?.isKind(of: LogInViewController.self))!
        {
            return .portrait
        }
        return .landscapeRight
    }
}

W miejscu LoginViewControllerwykorzystania, które UIViewControllerchcesz pokazać. W moim przypadku chcę pokazać LoginViewControllerw Portraittrybie innym ViewControllersw landscapetrybie.

Ramakrishna
źródło
-1

Aby rozwiązać ten problem, użyj następującej metody

- (NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait;
}

zwróć tylko wybraną orientację !!!

maxfiresolutions
źródło
3
Zrobiłem to, jak napisałem. Dzięki temu mój kontroler widoku nie obraca się, ale nie zmusza go do powrotu do jedynej obsługiwanej orientacji, gdy do niego wracam.
Harald Bögeholz
To nie działa na mnie. Nawet po uwzględnieniu tego w moim kontrolerze widoku widok nadal się obraca. Co daje?
shim
dlaczego głosować przeciw maxfiresolutions? U mnie zadziałało i ta sama metoda, którą podał @Flo, to otrzymanie wielu pozytywnych opinii.
ViruMax