Підтримувані орієнтації не мають спільної орієнтації з додатком, і якщо Autorotate повертає ТАК


92

Мій додаток (iPad; iOS 6) є лише альбомним, але коли я намагаюся використовувати UIPopoverController для відображення бібліотеки фотографій, він видає цю помилку: Supported orientations has no common orientation with the application, and shouldAutorotate is returning YES.я намагався змінити багато коду навколо, але мені не пощастило.


1
ви повинні прийняти відповідь. Є багато людей для допомоги, а для інших людей, які мають таку ж проблему, це допомагає, коли ви ставите правильну відповідь на свою проблему!
brush51

1
Немає! не працює рішення на iOS 7 :( (headbang)
AsifHabib

Найкраща відповідь тут stackoverflow.com/questions/20468335/…
Damien Romito

Відповіді:


94

В IOS6 ви підтримуєте орієнтацію інтерфейсу у трьох місцях:

  1. .Plist (або екран зведення цілей)
  2. Ваш UIApplicationDelegate
  3. Відображається UIViewController

Якщо ви отримуєте цю помилку, швидше за все, оскільки подання, яке ви завантажуєте у своєму UIPopover, підтримує лише портретний режим. Це може бути спричинено Game Center, iAd або вашим власним видом.

Якщо це ваш власний вигляд, ви можете виправити це, перевизначивши підтриманіInterfaceOrientations на своєму 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;
}

Якщо це не ваш власний вигляд (наприклад, GameCenter на iPhone), потрібно переконатися, що ваш .plist підтримує портретний режим. Вам також потрібно переконатися, що ваш UIApplicationDelegate підтримує подання, які відображаються в портретному режимі. Ви можете зробити це, відредагувавши свій .plist, а потім замінивши supportedInterfaceOrientation на вашому UIApplicationDelegate:

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

3
UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRightдорівнює UIInterfaceOrientationMaskAllButUpsideDown UIInterfaceOrientationMaskLandscapeLeft | UIInterfaceOrientationMaskLandscapeRightдорівнюєUIInterfaceOrientationMaskLandscape
Валерій Павлов

4
Або просто використовуйте UIInterfaceOrientationMaskAll.
Марк Ванг

Ідеально Навіть незважаючи на те, що "лише портрет" поповер буде працювати в альбомному режимі, він не може представити модально контролер перегляду лише в альбомному режимі.
Ніл Ехардт

Немає! Рішення не працював над прошивкою 7 :(. Stackoverflow.com/questions/23005351 / ...
AsifHabib

Працював на iOS 8. Хоча, довелося додати підтримку портретів до plist. Дякую.
Ярослав

65

Провівши багато часу на пошук способу уникнути підкласу та додавання тонни коду, ось моє рішення з одним рядком коду.

Створіть нову категорію UIImagePickerController та додайте

-(BOOL)shouldAutorotate{
    return NO;
}

Це все, шановні!


1
Працював і у мене, не пройшов повне тестування, але, схоже, поки що робить фокус.
migs647

2
Здається, це найкраще рішення.
Джуліан,

2
Працює! Це чудово, і це мені справді допомогло. Дякую доктору Луджі !!
брак

1
Приємно. Мені підходить для iOS 6. Ви також можете зробити це налаштовуваним у категорії для повної гнучкості.
Jared Egan

3
не працює в iOS7, метод категорії навіть не викликається (хоча включений в pch)
Peter Lapisu

43

Є інший випадок, коли може з’явитися це повідомлення про помилку. Я шукав годинами, поки не знайшов проблему. Ця тема дуже допомогла, прочитавши її пару разів.

Якщо ваш основний контролер подання повернуто в альбомну орієнтацію, і ви викликаєте власний контролер допоміжного перегляду, який повинен відображатися в книжковій орієнтації, це повідомлення про помилку може статися, коли ваш код виглядає так:

- (NSUInteger)supportedInterfaceOrientations {

    return UIInterfaceOrientationPortrait;
}

Пасткою тут був інтеліссенс xcode, запропонований "UIInterfaceOrientationPor Portrait", і мені це було все одно. На перший погляд це здавалося правильним.

Правильна маска названа

UIInterfaceOrientationMaskPortrait

Зверніть увагу на невеликий інфікс "Маска" , інакше ваш підзакон закінчиться винятком та згаданим вище повідомленням про помилку.

Нові переліки трохи змінені. Старі перелічення повертають недійсні значення!

(в UIApplication.h ви можете побачити нову декларацію: UIInterfaceOrientationMaskPor Portrait = (1 << UIInterfaceOrientationPor Portrait) )

Рішення:

- (BOOL)shouldAutorotate {

    return YES;
}

- (NSUInteger)supportedInterfaceOrientations {

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

    return UIInterfaceOrientationMaskPortrait;
} 

Швидке використання

override func shouldAutorotate() -> Bool {

    return true
}

override func supportedInterfaceOrientations() -> Int {

    return Int(UIInterfaceOrientationMask.Portrait.rawValue)
}

5
трапилося зі мною з тієї самої причини
Ченьсінь

Я хотів би, щоб Apple просто зробив тип повернення UIInterfaceOrientationMask, щоб було трохи більш очевидно, що потрібно повернути.
LightningStryk

Відповідь Джекпірза виглядає правильно. Але якщо заглянути в список info.plist, є UISupportedInterfaceOrientations з UIInterfaceOrientationPor Portrait, UIInterfaceOrientationLandscapeLeft, UIInterfaceOrientationLandscapeRight. Немає МАСКА тут
onmyway133

1
@onmyway: Це правда, значення plist не змінилися. У попередній версії iOS Apple використовувала значення "не" маски всередині коду. Це деякі застарілі речі. Я припускаю, що apple зараз внутрішньо змінює значення plist.
JackPearse

Раніше мій додаток працював без цієї проблеми, що виникала на симуляторі iPad для Xcode 6.2. І він зазнав аварії після того, як я кілька днів тому перейшов на Xcode 6.3. Тепер це рішення вирішує мою проблему. Thx a lot :-)
Золотий палець

22

У мене була подібна проблема при презентації засобу вибору зображень у альбомній програмі. Як запропонував доктор Луїджі, я додав наступну категорію на початку свого контролера.

// 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

Найпростіше додати ці рядки безпосередньо перед @ реалізацією вашого .m-файлу ViewController.


У мене є додаток лише для портретів! і я хочу показати Камеру в альбомному режимі. будь-яке рішення ?????
AsifHabib

Траусти не працювали? у мене така сама проблема, і я спробував ваш код, але все одно виглядає той самий виняток. *** Завершення програми через невпійманий виняток "UIApplicationInvalidInterfaceOrientation", причина: "Підтримувані орієнтації не мають загальної орієнтації з додатком, і shouldAutorotate повертає ТАК ..... ... я також ставлю точку зупинки на метод категорії UIimagePickerView shouldAutorotate, що досягає там, і повертає ні, але все ж даю цей виняток .... Моя програма - це лише програма Landscape ... будь ласка, допоможіть мені
Vishal16

Також працює, щоб змусити SKStoreProductViewController відображатись у портретному режимі, коли вся програма знаходиться в альбомному режимі в iOS 8. Подякуємо.
Ярослав

11

Я зіткнувся з тим самим повідомленням про помилку в своєму коді. Я знайшов це, це помилка, про яку повідомляє Apple:

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

Його рішення - виправити це в AppDelegate. Я реалізував це, і це працює для мене!


До речі, спочатку я знайшов це за адресою: stackoverflow.com/questions/12522491/…
Роббі

Це була правильна відповідь, безпосередньо від Apple, і тоді мені просто довелося слідувати тим самим інструкціям, але зробити це в Swift для програми, націленої на iOS 8. Все працює чудово. AppDelegate встановлює підтримуваніInterfaceOrientationsForWindow як альбомну, так і книжкову, кожен окремий швидкий набір файлів перевизначає функцію supportedInterfaceOrientations на альбомну, щоб вигляд не обертався, але коли портретний вигляд (у моєму випадку SKStoreProductViewController) потрібно завантажити, він працює!
RanLearns

Боже, існує так багато запропонованих рішень, і це, безумовно, не має найвищих балів, але насправді є правильним. Перевірено на iOS 10 і 9. Більше нічого не працює.
Дем'ян Тернер

6

У мене була та сама проблема, і ця відповідь https://stackoverflow.com/a/12523916 працює для мене. Цікаво, чи є більш елегантне рішення.

Мій код:

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];

Я спробував це зробити, але коли я натискаю кнопку, щоб викликати код, але нічого не відображається, я також спробував додати @interface NonRotatingUIImagePickerController : UIImagePickerController @end @implementation NonRotatingUIImagePickerController - (BOOL)shouldAutorotate { return NO; } @endдо коду, але мій код не виявив NonRotatingUIImagePickerController.
Долина Світанок

1
Неважливо, він виявляє NonRotatingUIImagePickerController зараз, але нічого не відображається досі ... @poetowen
Доля Світанок

4

iOS 8 - ви можете використовувати UIModalPresentationPopover без будь-яких хаків для відображення в popover. Не ідеально, але краще нічого.

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

Редагувати: можливо, спробувати різні UIModalPresentationStyles - можливо, більше буде працювати в альбомному режимі.


3
- (BOOL)shouldAutorotate {
    return NO;
}

-(NSUInteger)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskPortrait;
}

This removes the crash.

2

Іншим варіантом, який вирішив мої проблеми, було створити підклас UIImagePickerController і замінити наведений нижче метод

@interface MyImagePickerController ()

@end

@implementation MyImagePickerController

- (NSUInteger)supportedInterfaceOrientations {
    return UIInterfaceOrientationMaskLandscape;
}

Використовуйте це замість UIImagePickerController, і все працює нормально.


1

Створення категорії дуже корисно для виправлення цієї помилки. І не забудьте імпортувати створену категорію. Це додасть відсутній метод до UIImagePickerController, а на iOS 6 він обмежить його роботу лише у книжковому режимі, оскільки в документації зазначено btw.

Можливо, інші рішення спрацювали. Але з SDK для iOS 8.x, скомпільованим для розгортання на iOS 6.1, це здається шляхом.

.H-файл:

#import <UIKit/UIKit.h>

@interface UIImagePickerController (iOS6FIX)

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

@end

.M-файл:

#import "UIImagePickerController+iOS6FIX.h"

@implementation UIImagePickerController (iOS6FIX)

- (BOOL) shouldAutorotate {
    return NO;
}

- (UIInterfaceOrientation) preferredInterfaceOrientationForPresentation {
    return UIInterfaceOrientationPortrait;
}

@end

1

Стрімкий 3

let imagePicker = UIImagePickerController()

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

present(imagePicker, animated: true)

0

Я зіткнувся з цією проблемою аварійного завершення роботи при неявному перетворенні UIInterfaceOrientationPortraitуUIInterfaceOrientationMaskPortrait значення, що повертається.

Більше довідкового коду UIPageViewControllerDelegate, просто FYI для всіх вас.

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

0

Я щойно вирішив проблему для 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
    }
}

Дякую, хлопці, за відповіді. Я просто вирізав відпрацьований код і просто переробив його.


0

Swift 4 і вище, припускаючи, що вся програма знаходиться в альбомному режимі, і вам потрібно представити один контролер у портретному режимі. У контролер подання, який повинен бути портретним, додайте наступне:

override open var supportedInterfaceOrientations: UIInterfaceOrientationMask {
    return .portrait
}

open override var shouldAutorotate: Bool {
    return false
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.