Obsługiwane orientacje nie mają wspólnej orientacji z aplikacją i jeśli Autorotate zwraca TAK ”


94

Moja aplikacja (iPad; iOS 6) jest aplikacją działającą wyłącznie w trybie poziomym, ale kiedy próbuję użyć kontrolera UIPopoverController do wyświetlenia biblioteki zdjęć, zgłasza ten błąd: Supported orientations has no common orientation with the application, and shouldAutorotate is returning YES.próbowałem zmienić dużo kodu, ale nie miałem szczęścia.


1
powinieneś przyjąć odpowiedź. jest wiele osób do pomocy, a dla innych osób, które mają ten sam problem, pomocne jest zaznaczenie poprawnej odpowiedzi na swój problem!
szczotka51

1
Nie! żadne rozwiązanie nie działa na iOS 7 :( (headbang)
AsifHabib

Odpowiedzi:


95

W IOS6 obsługujesz orientacje interfejsu w trzech miejscach:

  1. .Plist (lub ekran podsumowania celu)
  2. Twój UIApplicationDelegate
  3. Wyświetlany UIViewController

Jeśli otrzymujesz ten błąd, najprawdopodobniej jest to spowodowane tym, że widok, który ładujesz w swoim UIPopover, obsługuje tylko tryb portretowy. Może to być spowodowane przez Game Center, iAd lub Twój własny widok.

Jeśli jest to Twój własny widok, możesz to naprawić, zastępując supportedInterfaceOrientations w UIViewController:

- (NSUInteger) supportedInterfaceOrientations
{
     //Because your app is only landscape, your view controller for the view in your
     // popover needs to support only landscape
     return UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight;
}

Jeśli to nie jest Twój własny widok (na przykład GameCenter na iPhonie), musisz się upewnić, że plik .plist obsługuje tryb portretowy. Musisz również upewnić się, że UIApplicationDelegate obsługuje widoki wyświetlane w trybie pionowym. Możesz to zrobić, edytując swój plik .plist, a następnie zastępując obsługiwaną opcję InterfaceOrientation w UIApplicationDelegate:

- (NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
    return UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRight;
}

3
UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRightwynosi UIInterfaceOrientationMaskAllButUpsideDown UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRightrównychUIInterfaceOrientationMaskLandscape
Valerii Pawłowa

4
Lub po prostu użyj UIInterfaceOrientationMaskAll.
Mark Wang

Idealny. Mimo że popover „tylko portret” będzie działał w orientacji poziomej, nie może modalnie prezentować kontrolera widoku tylko w orientacji poziomej.
Neal Ehardt

Nie! Rozwiązanie nie pracował na iOS 7 :(. Stackoverflow.com/questions/23005351/...
AsifHabib

Pracował na iOS 8. Chociaż musiałem dodać obsługę portretu do plist. Dziękuję Ci.
Jarosław

65

Po spędzeniu dużo czasu na szukaniu sposobu na uniknięcie podklas i dodawanie mnóstwa kodu, oto moje rozwiązanie z jednym wierszem kodu.

Utwórz nową kategorię UIImagePickerController i dodaj

-(BOOL)shouldAutorotate{
    return NO;
}

To wszystko ludzie!


1
U mnie też zadziałał, nie został w pełni przetestowany, ale wydaje się, że jak dotąd działa.
migs647

2
To wydaje się być najlepszym rozwiązaniem.
Julian,

2
Pracuje! To jest świetne i naprawdę pomogło mi w uszczypnięciu. Dzięki Dr Luiji !!
nawias

1
Ładny. U mnie działa na iOS 6. Możesz również ustawić to konfigurowalne w kategorii dla pełnej elastyczności.
Jared Egan,

3
nie działa w iOS7, metoda kategorii nie jest nawet wywoływana (chociaż jest zawarta w pch)
Peter Lapisu

43

W innym przypadku może pojawić się ten komunikat o błędzie. Szukałem godzinami, aż znalazłem problem. Ten wątek był bardzo pomocny po kilkukrotnym przeczytaniu.

Jeśli główny kontroler widoku jest obrócony do orientacji poziomej i wywołujesz niestandardowy kontroler widoku podrzędnego, który powinien być wyświetlany w orientacji pionowej, ten komunikat o błędzie może się pojawić, gdy kod wygląda następująco:

- (NSUInteger)supportedInterfaceOrientations {

    return UIInterfaceOrientationPortrait;
}

Pułapka polegała na tym, że inteligencja xcode zasugerowała „UIInterfaceOrientationPortrait” i nie przejmowałem się tym. Na pierwszy rzut oka wydawało się to słuszne.

Nazwa prawej maski

UIInterfaceOrientationMaskPortrait

Zwróć uwagę na mały wrostek „Maska” , w przeciwnym razie Twój widok podrzędny zakończy się wyjątkiem i wspomnianym powyżej komunikatem o błędzie.

Nowe wyliczenia są nieco przesunięte. Stare wyliczenia zwracają nieprawidłowe wartości!

(w UIApplication.h można zobaczyć nową deklarację: UIInterfaceOrientationMaskPortrait = (1 << UIInterfaceOrientationPortrait) )

Rozwiązaniem jest:

- (BOOL)shouldAutorotate {

    return YES;
}

- (NSUInteger)supportedInterfaceOrientations {

    // ATTENTION! Only return orientation MASK values
    // return UIInterfaceOrientationPortrait;

    return UIInterfaceOrientationMaskPortrait;
} 

W szybkim użyciu

override func shouldAutorotate() -> Bool {

    return true
}

override func supportedInterfaceOrientations() -> Int {

    return Int(UIInterfaceOrientationMask.Portrait.rawValue)
}

5
zdarzyło mi się z tego samego powodu
ChenXin

Chciałbym, żeby firma Apple po prostu utworzyła zwracany typ UIInterfaceOrientationMask, aby było trochę bardziej oczywiste, co należy zwrócić.
LightningStryk

Odpowiedź Jackpearse wygląda na poprawną. Ale kiedy spojrzymy na info.plist, jest tam UISupportedInterfaceOrientations z UIInterfaceOrientationPortrait, UIInterfaceOrientationLcapesLeft, UIInterfaceOrientationLcapesRight. Nie MASK tutaj
onmyway133

1
@onmyway: To prawda, wartości plist się nie zmieniły. W poprzedniej wersji na iOS firma Apple używała „nie” wartości maski wewnątrz kodu. To jest jakieś dziedzictwo. Zakładam, że firma apple nieznacznie zmienia teraz wartości plist wewnętrznie.
JackPearse

Moja aplikacja działała bez tego problemu z awarią na symulatorze iPada Xcode 6.2. I zawiesił się po aktualizacji do Xcode 6.3 kilka dni temu. Teraz to rozwiązanie rozwiązuje mój problem. Wielkie dzięki :-)
Golden Thumb

22

Miałem podobny problem podczas prezentowania selektora obrazów w aplikacji tylko w orientacji poziomej. Zgodnie z sugestią Dr. Luiji na początku mojego kontrolera dodałem następującą kategorię.

// This category (i.e. class extension) is a workaround to get the
// Image PickerController to appear in landscape mode.
@interface UIImagePickerController(Nonrotating)
- (BOOL)shouldAutorotate;
@end

@implementation UIImagePickerController(Nonrotating)

- (BOOL)shouldAutorotate {
  return NO;
}
@end

Najłatwiej jest dodać te wiersze tuż przed @implementacją pliku .m ViewController.


Mam aplikację tylko do portretów! i chcę pokazać kamerę w trybie poziomym. jakieś rozwiązanie ?????
AsifHabib

Trausti nie działał? Mam ten sam problem i wypróbowałem Twój kod, ale nadal pojawia się ten sam wyjątek *** Zamykanie aplikacji z powodu niezłapanego wyjątku „UIApplicationInvalidInterfaceOrientation”, powód: „Obsługiwane orientacje nie mają wspólnej orientacji z aplikacją, a funkcja shouldAutorotate zwraca TAK ..... ... umieściłem również punkt przerwania w metodzie kategorii UIimagePickerView powinnaAutorotate dotrzeć do tego miejsca i zwraca nie, ale nadal daje ten wyjątek .... Moja aplikacja jest tylko aplikacją
poziomą

Działa również w celu wymuszenia na SKStoreProductViewController przedstawienia w orientacji pionowej, gdy cała aplikacja jest pozioma w systemie iOS 8. Dziękuję.
Jarosław

11

W moim kodzie pojawił się ten sam komunikat o błędzie. Znalazłem to, to błąd zgłoszony przez Apple:

https://devforums.apple.com/message/731764#731764

Jego rozwiązaniem jest naprawienie tego w AppDelegate. Wdrożyłem to i działa na mnie!


Nawiasem mówiąc, pierwotnie znalazłem to pod adresem: stackoverflow.com/questions/12522491/…
Robby

To była właściwa odpowiedź, prosto od Apple, a potem musiałem postępować zgodnie z tymi samymi instrukcjami, ale zrobiłem to w Swift dla aplikacji na iOS 8. Wszystko działa świetnie. Obsługiwane zestawy AppDelegateInterfaceOrientationsForWindow zarówno na poziomą, jak i pionową, każdy pojedynczy zestaw plików Swift zastępuje obsługiwaną funkcjęInterfaceOrientations to Landscape, aby widok nie obracał się, ale gdy widok pionowy (w moim przypadku SKStoreProductViewController) musi zostać załadowany, działa!
RanLearns

Jezu, jest tak wiele sugerowanych rozwiązań, a to zdecydowanie nie ma najwyższych punktów, ale rzeczywiście jest właściwe. Testowane na iOS 10 i 9. Nic innego nie działa.
Demian Turner,

6

Miałem ten sam problem i ta odpowiedź https://stackoverflow.com/a/12523916 działa dla mnie. Ciekawe, czy istnieje bardziej eleganckie rozwiązanie.

Mój kod:

UIImagePickerController  *imagePickerController = [[NonRotatingUIImagePickerController alloc] init];
imagePickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;

UIPopoverController  *popoverVC = [[UIPopoverController alloc] initWithContentViewController:imagePickerController];    

[popoverVC presentPopoverFromRect:frame   // did you forget to call this method?
                           inView:view
         permittedArrowDirections:UIPopoverArrowDirectionAny
                         animated:YES];

Próbowałem to zrobić, ale kiedy @interface NonRotatingUIImagePickerController : UIImagePickerController @end @implementation NonRotatingUIImagePickerController - (BOOL)shouldAutorotate { return NO; } @endkliknąłem przycisk, aby wywołać kod, ale nic nie zostało wyświetlone, próbowałem również dodać do kodu, ale mój kod nie wykrył NonRotatingUIImagePickerController.
Destiny Dawn,

1
Nieważne, teraz wykrywa NonRotatingUIImagePickerController, ale nic nie jest wyświetlane ... @poetowen
Destiny Dawn

4

iOS 8 - możesz używać UIModalPresentationPopover bez żadnych hacków do wyświetlania w popover. Nie idealne, ale lepsze niż nic.

imagePicker.modalPresentationStyle = UIModalPresentationPopover;
imagePicker.popoverPresentationController.sourceView = self.view;
imagePicker.popoverPresentationController.sourceRect = ((UIButton *)sender).frame;

Edycja: być może wypróbuj różne style UIModalPresentationStyle - może więcej będzie działać w krajobrazie.


3
- (BOOL)shouldAutorotate {
    return NO;
}

-(NSUInteger)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskPortrait;
}

This removes the crash.

2

Inną opcją, która rozwiązała moje problemy, było utworzenie podklasy UIImagePickerController i zastąpienie poniższej metody

@interface MyImagePickerController ()

@end

@implementation MyImagePickerController

- (NSUInteger)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskLandscape;
}

Użyj tego zamiast UIImagePickerController i wszystko działa dobrze.


1

Utworzenie kategorii jest bardzo pomocne w naprawieniu tego błędu. I nie zapomnij zaimportować utworzonej kategorii. Spowoduje to dodanie brakującej metody do UIImagePickerController, a na iOS 6 ograniczy ją do pracy w orientacji pionowej tylko zgodnie z dokumentacją btw.

Inne rozwiązania mogły zadziałać. Jednak w przypadku SDK dla iOS 8.x skompilowanego do wdrożenia w iOS 6.1 wydaje się, że jest to właściwe.

Plik .h:

#import <UIKit/UIKit.h>

@interface UIImagePickerController (iOS6FIX)

- (BOOL) shouldAutorotate;
- (UIInterfaceOrientation) preferredInterfaceOrientationForPresentation;

@end

Plik .m:

#import "UIImagePickerController+iOS6FIX.h"

@implementation UIImagePickerController (iOS6FIX)

- (BOOL) shouldAutorotate {
    return NO;
}

- (UIInterfaceOrientation) preferredInterfaceOrientationForPresentation {
    return UIInterfaceOrientationPortrait;
}

@end

1

Szybki 3

let imagePicker = UIImagePickerController()

imagePicker.modalPresentationStyle = .popover
imagePicker.popoverPresentationController?.sourceView = sender // you can also pass any view 

present(imagePicker, animated: true)

0

Napotkałem ten problem z awarią podczas konwersji UIInterfaceOrientationPortraitna UIInterfaceOrientationMaskPortraitniejawnie jako wartość zwracaną.

Więcej tła kodu UIPageViewControllerDelegate, tylko do Twojej wiadomości dla wszystkich.

 -(UIInterfaceOrientationMask)pageViewControllerSupportedInterfaceOrientations:
(UIPageViewController *)pageViewController
{
    # return UIInterfaceOrientationPortrait;    # wrong
    return UIInterfaceOrientationMaskPortrait;  # correct
}

0

Właśnie rozwiązałem problem ze Swift 4.x

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    configureVideoOrientation()
}

override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
    super.viewWillTransition(to: size, with: coordinator)
    coordinator.animate(alongsideTransition: nil, completion: { [weak self] _ in
        self?.configureVideoOrientation()
    })
}

private func configureVideoOrientation() {
    guard let previewLayer = self.previewLayer, let connection = previewLayer.connection else { return }
    if connection.isVideoOrientationSupported {
        let orientation = UIApplication.shared.statusBarOrientation
        switch (orientation) {
        case .portrait:
            previewLayer.connection?.videoOrientation = .portrait
        case .landscapeRight:
            previewLayer.connection?.videoOrientation = .landscapeRight
        case .landscapeLeft:
            previewLayer.connection?.videoOrientation = .landscapeLeft
        case .portraitUpsideDown:
            previewLayer.connection?.videoOrientation = .portraitUpsideDown
        default:
            previewLayer.connection?.videoOrientation = .portrait
        }

        previewLayer.frame = self.view.bounds
    }
}

Dziękuję również za wasze odpowiedzi. Właśnie wyciąłem działający kod i po prostu go przeformułowałem.


0

Swift 4 i nowsze, zakładając, że cała aplikacja jest w orientacji poziomej i musisz przedstawić pojedynczy kontroler w pionie. W kontrolerze widoku, który ma być portretem, dodaj:

override open var supportedInterfaceOrientations: UIInterfaceOrientationMask {
    return .portrait
}

open override var shouldAutorotate: Bool {
    return false
}
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.