Подтвердить что ты не робот

Как заблокировать портретную ориентацию только для основного вида с помощью быстрой

Я создал приложение для iPhone, используя swift, который состоит из многих представлений, встроенных в контроллер навигации. Я хотел бы заблокировать основной вид ориентации "Портрет" и только подчиненность контроллера навигации, заблокированного в альбомной ориентации. Вот пример того, что я имею в виду:

  • UINavigationController
    • UiViewController1 (заблокирован в портрете). Контроллер начального представления с кнопкой, расположенной на панели навигации, которая дает пользователю возможность доступа к спискам, где могут быть выбраны другие виды.
    • UIViewController2 (заблокирован в ландшафте)
    • UiViewController3 (портрет и пейзаж)
    • UiViewController4 (портрет и пейзаж)
    • ...
    • ...

Как я могу это сделать?

4b9b3361

Ответ 1

В соответствии с Swift Apple Docs для supportedInterfaceOrientations:

Обсуждение

Когда пользователь изменяет ориентацию устройства, система вызывает этот метод на контроллере корневого представления или на верхнем представленном контроллере представления, который заполняет окно. Если контроллер просмотра поддерживает новую ориентацию, контроллер окна и представления поворачивается в новую ориентацию. Этот метод вызывается только в том случае, если метод viewAutorotate должен иметь значение true.

Ваш навигационный контроллер должен переопределить shouldAutorotate и supportedInterfaceOrientations, как показано ниже. Я сделал это в расширении UINavigationController для удобства:

extension UINavigationController {
    public override func shouldAutorotate() -> Bool {
        return true
    }

    public override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
        return (visibleViewController?.supportedInterfaceOrientations())!
    }
}

И ваш главный диспетчер представлений (портрет всегда) должен иметь:

override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
    return UIInterfaceOrientationMask.Portrait
}

Затем в ваших подвидных контроллерах вы хотите поддерживать портрет или пейзаж:

override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
    return UIInterfaceOrientationMask.All
}

Изменить: обновлено для iOS 9: -)

Ответ 2

Также ответил [здесь]

Все может стать довольно беспорядочным, если у вас сложная иерархия представлений, например, наличие нескольких контроллеров навигации и/или контроллеров таблиц.

Эта реализация помещает его в отдельные контроллеры представлений, чтобы установить, когда они хотели бы заблокировать ориентации, вместо того, чтобы полагаться на App Delegate, чтобы найти их, итерации через subviews или полагаясь на наследование.

Swift 3

В 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
}

В другом глобальном классе struct или helper здесь я создал 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")
    }

}

Затем в желаемом ViewController вы хотите заблокировать ориентации:

 override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(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)
}

Ответ 3

Если ваше представление встроено в навигационный контроллер в раскадровке, установите делегат диспетчера навигации UINavigationControllerDelegate и добавьте следующий метод

class ViewController: UIViewController, UINavigationControllerDelegate {
    func navigationControllerSupportedInterfaceOrientations(navigationController: UINavigationController) -> UIInterfaceOrientationMask {
        return UIInterfaceOrientationMask.Portrait
    }
}

Ответ 4

Обновление: если у вас возникли проблемы с настройкой ориентации сразу после запуска приложения в iOS 10, попробуйте сделать это в ObjC вместо Swift и с помощью class MyNavigationController: MyNavigationControllerBase:

@implementation ABNavigationControllerBase
- (NSUInteger)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait;
}
@end

Swift 3:

class MyNavigationController: UINavigationController {
    override func viewDidLoad() {
        super.viewDidLoad()
        UIDevice.current.setValue(UIInterfaceOrientation.portrait.rawValue, forKey: "orientation")
    }
    override var shouldAutorotate: Bool {
        return false
    }
    override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        return .portrait
    }
    override var preferredInterfaceOrientationForPresentation: UIInterfaceOrientation {
        return .portrait
    }
}

Ответ 5

Тот же самый ответ JasonJasonJason в Swift 4. 2+ (он работал правильно с iOS 11)

1- Переопределить mustAutorotate и supportInterfaceOrientations, как показано ниже.

extension UINavigationController {

open override var shouldAutorotate: Bool {
    return true
}

open override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
    return (visibleViewController?.supportedInterfaceOrientations)!
    }
}

2- И ваш главный view-контроллер (портретный) должен иметь:

 public override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
    return UIInterfaceOrientationMask.portrait
}

3- Затем, в ваших подчиненных контроллерах, которые вы хотите поддерживать книжную или альбомную ориентацию:

 public override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
    return UIInterfaceOrientationMask.all
}

Ответ 6

Важно подумать о том, чтобы описать поддерживаемые ориентации интерфейса для всего приложения в AppDelegate. Например, чтобы заблокировать все представления на портрете, просто выполните следующее:

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

Многие люди ищут только этот ответ, по-разному задав этот вопрос, поэтому я надеюсь, что вы можете извинить меня. Работает в Swift 3.0

Ответ 7

В главном контроллере, где вы хотите портрет,

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

self.orientation = UIInterfaceOrientationMaskPortrait;
//Or self.orientation = UIInterfaceOrientationPortraitUpsideDown
}

и в subVC, где вы хотите использовать ландшафт

  self.orientation =  UIInterfaceOrientationLandscapeLeft:
   self.orientation =  UIInterfaceOrientationLandscapeRight:

или вы можете переопределить этот метод

- (NSUInteger)supportedInterfaceOrientations
{
  return UIInterfaceOrientationMaskPortrait;
} 

Так я бы сделал это с Obj-c в iOS7, я думаю, что этот код будет работать и в iOS8 тоже

Ответ 8

Вот быстрое обновление: -

override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
    return UIInterfaceOrientationMask.Portrait
}

Ответ 9

Отредактировано для swift2.0:

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

override func supportedInterfaceOrientations() -> UIInterfaceOrientationMask {
    return [.Portrait, .PortraitUpsideDown]
}

Ответ 10

Это синтаксис для Swift 3 (XCode 8.2 beta), где эти методы преобразуются в свойства:

extension UINavigationController {
    override open var shouldAutorotate: Bool {
        return false
    }
}

class ViewController: UIViewController {

    /*
            ...
    */

    override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
        return UIInterfaceOrientationMask.portrait
    }
}

Ответ 11

Вам нужно применить это к контроллеру верхнего уровня. Тем не менее, вы можете сделать это чистым/простым способом, подклассифицировав свой контроллер верхнего уровня и установив в нем переменную, которая ссылается каждый раз, когда вы вызываете:

shouldAutoRotate()

который вызывается, когда устройство обнаруживает изменение ориентации и предшествует вызову:

supportedInterfaceOrientations()//this is only called if shouldAutoRotate() returns true

Например, скажем, мой контроллер верхнего уровня является TabBarController:

class SomeSubclassTabBarViewController: UITabBarController { //This subclass allows us to pass along data to each of the tabBars

var dataArray = StoredValues()//also useful for passing info between tabs
var shouldRotate: Bool = false


override func shouldAutorotate() -> Bool { //allow the subviews accessing the tabBarController to set whether they should rotate or not
    return self.shouldRotate
}

}

Затем в представлении, которое должно иметь возможность поворачивать экран, установите viewWillAppear() и viewWillDisappear() следующим образом:

override func viewWillAppear(animated: Bool) { //set the rotate capability to true
    let sharedTabBarController = self.tabBarController as SomeSubclassTabBarViewController
    sharedTabBarController.shouldRotate = true
}

override func viewWillDisappear(animated: Bool) {
    let sharedTabBarController = self.tabBarController as SomeSubclassTabBarViewController
    sharedTabBarController.shouldRotate = false
}

и на случай, если ваше приложение выйдет из строя на этом экране, вероятно, неплохо было бы явно указать значение shouldRotate: Bool для каждого из ваших представлений в методе viewWillLoad().

Ответ 12

В iOS8, если вы хотите заблокировать какой-то специальный ViewController, создайте расширение UINavigationController (в том случае, если вы его используете):

extension UINavigationController {
public override func shouldAutorotate() -> Bool {
if visibleViewController is YourViewController {
    return false
}
return true
}}

Ответ 13

Если ваше iOS-приложение работает только в альбомном режиме и вы хотите использовать камеру в ландшафтном режиме приложения, попробуйте следующее решение.

Шаг 1:

В вашем классе appdelegate.m

-(UIInterfaceOrientationMask)application:(UIApplication *)application
supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
    if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone){
        NSString *captionVal = [TMUtils getValueInUserDefault:@"CAPTION"];
        if ([captionVal isEqualToString:@"Camera"]) {
            return UIInterfaceOrientationMaskPortrait;
        }else{
            return UIInterfaceOrientationMaskLandscapeRight;
        }
    }else{
        return UIInterfaceOrientationMaskAllButUpsideDown;
    }
}

Здесь вы можете взять значение общего предпочтения CAPTION в качестве пары keyValue и сохранить значение "Камера".

Шаг 2: Теперь в вашем классе viewController.m в кнопке камеры действие установите общее значение предпочтения и откройте новый ViewController, который будет иметь функции камеры.

[TMUtils setValueInUserDefault: @"CAPTION" значение: @"Camera"];

Шаг 3: В функциональности камеры класс viewController.m устанавливает раскадровку с UIImageView и кнопкой возврата.

Теперь во ViewDidLoad функции камеры установлено viewController.m

- (void)viewDidLoad {
    [super viewDidLoad];

    if (![UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]) {
            NSLog(@"Error");
        } else {

            UIImagePickerController *pickerController = [[UIImagePickerController alloc] init];
            pickerController.modalPresentationStyle = UIModalPresentationCurrentContext; //this will allow the picker to be presented in landscape
            pickerController.delegate = self;
            pickerController.allowsEditing = YES;
            pickerController.sourceType = UIImagePickerControllerSourceTypeCamera;
            [self presentViewController:pickerController animated:YES completion:nil];
        }
}

Теперь в методе делегата UIImagePickerController установите изображение в UIImageView

- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {

        UIImage *chosenImage = info[UIImagePickerControllerOriginalImage];
        self.cameraImage.image = chosenImage;
        [picker dismissViewControllerAnimated:YES completion:NULL];
}

Теперь на камеру назад UIButton

- (IBAction)cameraBtnAction:(id)sender {
    [TMUtils setValueInUserDefault:@"CAPTION" value:@"NOCamera"];
    [self dismissViewControllerAnimated:YES completion:nil];
}

Он всегда будет проверять в соответствии с общим значением предпочтения в функции класса делегата для supportInterfaceOrientationsForWindow, ссылаясь на это значение, он позволяет функциональности камеры ViewController открывать камеру в портретном режиме и отдыхать, он снова возвращается в ландшафтный режим, который будет работать нормально.