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.