iOS: ориентация устройства при загрузке

Кажется, что когда мое приложение загружается, оно не знает своей текущей ориентации:

UIInterfaceOrientation orientation = [[UIDevice currentDevice] orientation];
if (orientation == UIDeviceOrientationPortrait) {
    NSLog(@"portrait");// only works after a rotation, not on loading app
}

Поворачивая устройство, я получаю правильную ориентацию, но при загрузке приложения, не меняя ориентацию, кажется, что использование [[UIDevice currentDevice] orientation] не знает текущую ориентацию.

Есть ли другой способ проверить это при первой загрузке приложения?

16 ответов

Решение

РЕДАКТИРОВАТЬ: я неправильно прочитал ваш вопрос. Это позволит вам запустить приложение в определенных направлениях. Просто понял, что вы пытаетесь выяснить ориентацию при запуске.

Есть способ проверить ориентацию строки состояния на UIApplication:

[[UIApplication sharedApplication] statusBarOrientation];

Оригинальный ответ

Попробуйте установить принятые приложением ориентации устройства в файле plist:

<key>UISupportedInterfaceOrientations</key>
<array>
    <string>UIInterfaceOrientationPortrait</string>
    <string>UIInterfaceOrientationLandscapeLeft</string>
    <string>UIInterfaceOrientationLandscapeRight</string>
</array>

Это будет означать, что ваше приложение поддерживает Портрет (кнопка "Домой" внизу), альбомную ориентацию влево и альбомную ориентацию вправо.

Затем в ваших UIViewControllers вам нужно будет переопределить shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation) метод возврата YES, когда приложение должно вращаться:

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {

     return interfaceOrientation == UIInterfaceOrientationPortrait || interfaceOrientation == UIInterfaceOrientationLandscapeLeft || interfaceOrientation == UIInterfaceOrientationLandscapeRight;
}

Это скажет UIViewController для автоматического поворота, если устройство находится в одной из ваших поддерживаемых ориентаций. Если вы хотите поддержать ориентацию вверх ногами (портрет с кнопкой "Домой" вверху), добавьте это к списку и просто верните ДА из этого метода.

Дайте нам знать, как это работает.

Я думаю, что это будет работать:

 [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];UIInterfaceOrientation orientation = [UIDevice currentDevice].orientation;

Согласно справке UIDevice:
Цитата:
"Значение этого свойства всегда возвращает 0, если уведомления об ориентации не были включены путем вызова beginGeneratingDeviceOrientationNotifications"
Сначала я предполагал, что это свойство всегда содержало текущую ориентацию, но, по-видимому, не так. Я предполагаю, что включение уведомлений обрабатывается для нас за кулисами в других ситуациях, когда свойство ориентации обычно доступно, поэтому не было очевидно, что это нужно делать вручную внутри делегата приложения.

Для тех, кто ищет ответ для Swift 3 или 4. просто добавьте этот код внутри блока viewDidLoad().

`let orientation = UIApplication.shared.statusBarOrientation
 if orientation == .portrait {
        // portrait   
 } else if orientation == .landscapeRight || orientation == 
.landscapeLeft{
         // landscape     
 }`

На нагрузке устройства ориентация может быть .Unknown или же .FaceUp, Чтобы выяснить, портрет это или пейзаж, я использую statusBarOrientation в качестве резервной копии, вот так:

    var portraitOrientation = UIDevice.currentDevice().orientation == .Portrait

    if UIDevice.currentDevice().orientation == .Unknown || UIDevice.currentDevice().orientation == .FaceUp {
        portraitOrientation = UIApplication.sharedApplication().statusBarOrientation == .Portrait
    }

Таким образом, я могу заверить, что portraitOrientation всегда говорит мне, если устройство находится в портретном режиме, и если нет, оно будет в альбомной. Даже при загрузке приложения в первый раз.

Вы можете сделать это, вставив следующее уведомление внутри

-(void)viewDidLoad

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(checkRotation:) name:UIApplicationDidChangeStatusBarOrientationNotification object:nil];

затем поместите следующий метод внутри вашего класса

-(void)checkRotation:(NSNotification*)notification
{
    UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;
    if(orientation == UIInterfaceOrientationLandscapeLeft || orientation == UIInterfaceOrientationLandscapeRight)
    {
         //Do your textField animation here
    }
}

Вышеупомянутый метод проверит ориентацию строки состояния ipad или iPhone и в соответствии с ней вы заставите сделать анимацию в необходимой ориентации.

Одна вещь, которую еще никто не коснулся, это то, что вы храните UIDeviceOrientation вводит в UIInterfaceOrientation переменная. Они разные и не должны рассматриваться как равные. Обратите внимание, что UIDeviceOrientationLeft равно UIInterfaceOrientationRight (поскольку интерфейс вращается в противоположном направлении по сравнению с устройством).

Swift 3 на основе кода @Marjin.

var portraitOrientation = UIDevice.current.orientation == .portrait

if UIDevice.current.orientation == .unknown || UIDevice.current.orientation == .faceUp {
     portraitOrientation = UIApplication.shared.statusBarOrientation == .portrait
}

if(portraitOrientation)
{
     // Portrait
}
else
{

}

Проблема в том, что [UIDevice currentDevice]orientation] иногда сообщает об ориентации устройства неправильно.

вместо этого используйте [[UIApplication sharedApplication]statusBarOrientation] который является UIInterfaceOrientation чтобы проверить это, вам нужно использовать UIInterfaceOrientationIsLandscape(orientation)

надеюсь это поможет.

Чтобы получить ориентацию из строки состояния, также важно, чтобы все ориентации были включены в файле plist.

Это настоящий ответ. Когда приложение запускается, его ориентация неизвестна. Он использует shouldAutorotateToInterfaceOrientation и supportInterfaceOrientations, чтобы решить, какую ориентацию выбрать.

Посмотрите, как я запускаю пример приложения в симуляторе iPhone 5.0 и поворачиваю его, используя приведенный ниже код и "Поддерживаемые ориентации интерфейса" со всеми 4 возможными ориентациями:

20:44:08.218 RotationTestApp Supported orientation: Portrait
20:44:08.222 RotationTestApp Supported orientation: Portrait (upside-down)
20:44:08.225 RotationTestApp Supported orientation: Landscape (home button on the right)
20:44:08.225 RotationTestApp Supported orientation: Landscape (home button on the left)
20:44:08.226 RotationTestApp shouldAutorotateToInterfaceOrientation: YES (current device orientation: UIDeviceOrientationUnknown, interface orientation wants: UIInterfaceOrientationPortrait)
20:44:08.237 RotationTestApp shouldAutorotateToInterfaceOrientation: YES (current device orientation: UIDeviceOrientationUnknown, interface orientation wants: UIInterfaceOrientationPortrait)
20:44:08.239 RotationTestApp shouldAutorotateToInterfaceOrientation: YES (current device orientation: UIDeviceOrientationUnknown, interface orientation wants: UIInterfaceOrientationPortrait)
20:44:08.240 RotationTestApp shouldAutorotateToInterfaceOrientation: YES (current device orientation: UIDeviceOrientationUnknown, interface orientation wants: UIInterfaceOrientationPortrait)
20:44:09.817 RotationTestApp shouldAutorotateToInterfaceOrientation: YES (device orientation: UIDeviceOrientationLandscapeLeft)
20:44:09.833 RotationTestApp shouldAutorotateToInterfaceOrientation: YES (device orientation: UIDeviceOrientationLandscapeLeft)
20:44:11.030 RotationTestApp shouldAutorotateToInterfaceOrientation: YES (device orientation: UIDeviceOrientationPortraitUpsideDown)
20:44:11.040 RotationTestApp shouldAutorotateToInterfaceOrientation: YES (device orientation: UIDeviceOrientationPortraitUpsideDown)
20:44:12.599 RotationTestApp shouldAutorotateToInterfaceOrientation: YES (device orientation: UIDeviceOrientationLandscapeRight)
20:44:12.609 RotationTestApp shouldAutorotateToInterfaceOrientation: YES (device orientation: UIDeviceOrientationLandscapeRight)
20:44:13.301 RotationTestApp shouldAutorotateToInterfaceOrientation: YES (device orientation: UIDeviceOrientationPortraitUpsideDown)

Я видел много фрагментов кода, но ни один из них не работает достаточно широко (iPad и iPhone, iOS 5.0+).

Вместо того, чтобы возиться с try-this-try-that, поместите следующее в ваш корневой vc:

#define ToNSString_BEGIN(T) \
NSString* T##ToNSString(T valueParameter) { \
switch (valueParameter) {

#define ToNSString_VALUE(value) \
case value: return @#value

#define ToNSString_END(T) \
} \
return @"(unknown)"; \
}

// NSString* UIInterfaceOrientationToNSString(UIInterfaceOrientation);
ToNSString_BEGIN(UIInterfaceOrientation);
ToNSString_VALUE(UIInterfaceOrientationPortrait);           // 1
ToNSString_VALUE(UIInterfaceOrientationPortraitUpsideDown); // 2
ToNSString_VALUE(UIInterfaceOrientationLandscapeLeft);      // 3
ToNSString_VALUE(UIInterfaceOrientationLandscapeRight);     // 4
ToNSString_END  (UIInterfaceOrientation);

// NSString* UIDeviceOrientationToNSString(UIDeviceOrientation);
ToNSString_BEGIN(UIDeviceOrientation);
ToNSString_VALUE(UIDeviceOrientationUnknown);               // 0
ToNSString_VALUE(UIDeviceOrientationPortrait);              // 1
ToNSString_VALUE(UIDeviceOrientationPortraitUpsideDown);    // 2
ToNSString_VALUE(UIDeviceOrientationLandscapeLeft);         // 3
ToNSString_VALUE(UIDeviceOrientationLandscapeRight);        // 4
ToNSString_VALUE(UIDeviceOrientationFaceUp);                // 5
ToNSString_VALUE(UIDeviceOrientationFaceDown);              // 6
ToNSString_END  (UIDeviceOrientation);



// Change this custom method to alter auto-rotation behavior on all supported iOS versions and platforms.
- (BOOL)allowAutoRotate:(UIInterfaceOrientation)interfaceOrientation
{
    NSUInteger interfaceOrientationAsMask = (1<<interfaceOrientation);
    return interfaceOrientationAsMask & [self supportedInterfaceOrientations];
}

// Reads from the project's-Info.plist
- (NSUInteger)supportedInterfaceOrientations
{
    static NSUInteger orientationsResult;

    if (!orientationsResult) {
        NSArray *supportedOrientations = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"UISupportedInterfaceOrientations"];

        for (id orientationString in supportedOrientations) {
            if ([orientationString isEqualToString:@"UIInterfaceOrientationPortrait"]) {
                orientationsResult |= UIInterfaceOrientationMaskPortrait;
                NSLog(@"Supported orientation: Portrait");
            } else if ([orientationString isEqualToString:@"UIInterfaceOrientationPortraitUpsideDown"]) {
                orientationsResult |= UIInterfaceOrientationMaskPortraitUpsideDown;
                NSLog(@"Supported orientation: Portrait (upside-down)");
            } else if ([orientationString isEqualToString:@"UIInterfaceOrientationLandscapeRight"]) {
                orientationsResult |= UIInterfaceOrientationMaskLandscapeRight;
                NSLog(@"Supported orientation: Landscape (home button on the left)");
            } else if ([orientationString isEqualToString:@"UIInterfaceOrientationLandscapeLeft"]) {
                orientationsResult |= UIInterfaceOrientationMaskLandscapeLeft;
                NSLog(@"Supported orientation: Landscape (home button on the right)");
            } else {
                NSLog(@"Unrecognized orientation '%@' in mainBundle plist, key UISupportedInterfaceOrientations", orientationString);
            }
        }
    }
   return orientationsResult;
}

// iOS 6+ (not yet used in 6.0.1)
- (BOOL)shouldAutorotate
{
    UIDeviceOrientation interfaceOrientationFromDevice = [UIDevice currentDevice].orientation;
    BOOL result = [self allowAutoRotate:interfaceOrientationFromDevice];
    NSString *currentDeviceOrientation = UIDeviceOrientationToNSString(interfaceOrientationFromDevice);
    NSLog(@"shouldAutorotate: %s (current orientation %@)", result ? "YES" : "NO", currentDeviceOrientation);
    return result;
}

// iOS 2.0 - 5.1 (iOS 6+ deprecated, 6.0.1 still works)
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    NSString* orientationString;
    UIDeviceOrientation interfaceOrientationFromDevice = [UIDevice currentDevice].orientation;

    if ((int)interfaceOrientation != (int)interfaceOrientationFromDevice) {
        orientationString = [NSString stringWithFormat:@"current device orientation: %@, interface orientation wants: %@",
                             UIDeviceOrientationToNSString(interfaceOrientationFromDevice),
                             UIInterfaceOrientationToNSString(interfaceOrientation)
                             ];
    } else {
        orientationString = [NSString stringWithFormat:@"device orientation: %@", UIDeviceOrientationToNSString(interfaceOrientationFromDevice)
                             ];
    }

    BOOL result = [self allowAutoRotate:interfaceOrientation];
    NSLog(@"shouldAutorotateToInterfaceOrientation: %s (%@)",
          result ? "YES" : "NO",
          orientationString);
    return result;
}

Существует все еще острая проблема анимации перехода, не использующей текущую ориентацию. Я предполагаю, что создание подклассов каждого VC и установка некоторой ориентации на делегат push / notify на pop - это путь.

Также важно:

shouldAutorotateToInterfaceOrientation не работает

tabBarController и navigationControllers в ландшафтном режиме, эпизод II

Попробуй это[[UIApplication sharedApplication] statusBarOrientation];

или реализовать это в приложении делегата

(NSUInteger)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window
{
    UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
}

оно работает

Попробуйте акселерометр, чтобы получить его показания, UIAccelerometer, получить sharedAccelerometer, установить его делегат, получить показания, выяснить оттуда ориентацию.

Я до сих пор использую этот рабочий фрагмент кода для iphone 4:

-(void)deviceOrientationDidChange:(NSNotification *)notification{

//Obtaining the current device orientation
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];    

int value = 0;

if(orientation == UIDeviceOrientationPortrait)
{
    value = 0;

}else if(orientation == UIDeviceOrientationLandscapeLeft)
{
    value = 90;

}else if(orientation == UIDeviceOrientationLandscapeRight)
{

    value = -90;

}

CGAffineTransform cgCTM = CGAffineTransformMakeRotation(DEGREES_TO_RADIANS(value));
[photoImageView setTransform:cgCTM];

}

Перепробовал все и без хороших результатов. Итак, что я сделал, когда я на ipad, - это оставил всю работу методам splitViewController, чтобы лишить законной силы barButton:

Для портрета:

- (void)splitViewController:(UISplitViewController *)svc willHideViewController:(UIViewController *)aViewController withBarButtonItem:(UIBarButtonItem *)barButtonItem forPopoverController: (UIPopoverController *)pc { NSlog(@"portrait");}

Для ландшафта:

- (void)splitViewController:(UISplitViewController *)svc willShowViewController:(UIViewController *)aViewController invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem{ NSlog(@"landscape");}

это всегда работает под нагрузкой.

Попробуй это. это работа для меня. В то время, когда метод didfinishedlaunch не обнаружил ориентацию устройства. его взять по умолчанию в качестве портрета. так. Я использую, чтобы проверить ориентацию бара статистики. Я проверяю этот код. поместите его в метод didfinishedlaunch в appdeleget.

UIInterfaceOrientation ориентация = [UIApplication sharedApplication].statusBarOrientation;

if(orientation == 0) {//Default orientation
    //UI is in Default (Portrait) -- this is really a just a failsafe.

    NSLog("for portrait");


}else if(orientation == UIInterfaceOrientationPortrait || orientation == UIInterfaceOrientationPortraitUpsideDown)
{

    NSLog("portrait");
}else if(orientation == UIInterfaceOrientationLandscapeLeft || orientation == UIInterfaceOrientationLandscapeRight)
{

    NSLog("Landscap");
}

Все выше опубликовали очень правильные ответы, но в качестве ОБНОВЛЕНИЯ: Apple принимает: вы должны использовать ориентации UIStatusBar, чтобы прочитать текущую ориентацию устройства:

Один из способов проверить текущую ориентацию устройства - использовать значения int как таковые внутри viewDidLoad метод:

    int orientationType = [[UIDevice currentDevice] orientation];

где рассмотрим следующее.,, - 1 = портрет (направо вверх) - 2 = портрет вверх ногами - 3 = пейзаж (справа) - 4 = пейзаж (слева)

и тогда вы могли бы использовать IF оператор для вызова метода после определения ориентации и так далее:

Надеюсь, что это было немного полезно для кого-то

Другие вопросы по тегам