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

Как определить ориентацию iPhone перед вращением

В моей программе я перемещаю вещи на основе вращения, но я не вращаю весь вид. Я использую:

  static UIDeviceOrientation previousOrientation = UIDeviceOrientationPortrait;

 - (void)applicationDidFinishLaunching:(UIApplication *)application {   
    [window addSubview:viewController.view];
    [window makeKeyAndVisible];
    [[NSNotificationCenter defaultCenter] addObserver:self
           selector:@selector(didRotate:)
           name:@"UIDeviceOrientationDidChangeNotification" object:nil];

}

- (void) didRotate:(NSNotification *)notification{  
UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];

    [self doRotationStuff:orientation: previousOrientation];
previousOrientation = orientation;

} 

Это работает до тех пор, пока при запуске программы ориентация устройства будет портретирована, но если начальная ориентация не будет ландшафтной или перевернутой, потому что [self doRotationStuff] производит изменения относительно разницы с предыдущей ориентацией.

Есть ли способ определить ориентацию либо при запуске, либо непосредственно перед вращением устройства?

4b9b3361

Ответ 1

В зависимости от ваших обстоятельств более простым вариантом может быть свойство interfaceOrientation класса UIViewController. Это правильно перед вращением.

Ответ 2

Обновлено:

Итак, из обсуждения комментариев кажется, что вы не можете полагаться на [UIDevice currentDevice].orientation, пока ориентация не изменится в первый раз. Если это так, вы могли бы взломать его, получив сырые показания акселерометра.

#define kUpdateFrequency 30  // Hz
#define kUpdateCount 15 // So we init after half a second
#define kFilteringFactor (1.0f / kUpdateCount)

- (void)applicationDidFinishLaunching:(UIApplication *)app
{
    [UIAccelerometer sharedAccelerometer].updateInterval = (1.0 / kUpdateFrequency);
    [UIAccelerometer sharedAccelerometer].delegate = self;
    accelerometerCounter = 0;
    ...
}

- (void)accelerometer:(UIAccelerometer *)accelerometer didAccelerate:(UIAcceleration *)accel
{
    // Average out the first kUpdateCount readings
    // acceleration_[xyz] are ivars typed float
    acceleration_x = (float)accel.x * kFilteringFactor + acceleration_x * (1.0f - kFilteringFactor);
    acceleration_y = (float)accel.y * kFilteringFactor + acceleration_y * (1.0f - kFilteringFactor);
    acceleration_z = (float)accel.z * kFilteringFactor + acceleration_z * (1.0f - kFilteringFactor);

    accelerometerCounter++;
    if (accelerometerCounter == kUpdateCount)
    {
        [self initOrientation];
        [UIAccelerometer sharedAccelerometer].delegate = nil;
    }
}

- (void)initOrientation
{
    // Figure out orientation from acceleration_[xyz] and set up your UI...
}

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

Возвращает ли [UIDevice currentDevice].orientation правильную ориентацию во время applicationDidFinishLaunching:? Если это так, вы можете настроить свой первоначальный интерфейс в соответствии с этой ориентацией.

Если это свойство не будет установлено до некоторого более позднего времени, вы можете попробовать поэкспериментировать с performSelector:afterDelay: для инициализации пользовательского интерфейса после небольшой задержки.

Этот пример кода из ответа Kendall ниже, добавленный здесь для полноты:

[self performSelector:@selector(getOriented) withObject:nil afterDelay:0.0f];

Я не уверен, что достаточно нулевой задержки - это означает, что код для getOriented будет работать во время первого прохода через цикл запуска события. Возможно, вам придется подождать дольше, чтобы показания акселерометра регистрировались на UIDevice.

Ответ 3

Морт, эти ответы кажутся несколько красной селедкой; Я не понимаю, почему вы не можете использовать следующий встроенный метод для класса UIViewController:

-(void) didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {}

Этот метод вызывается автоматически после того, как произошел поворот (а не с shouldAutorotateToInterfaceOrientation, который только сообщает вам об этом). Удобно, переменная 'fromInterfaceOrientation' содержит предыдущую ориентацию. Как сказано в документации, вы можете предположить, что свойство interfaceOrientation представления уже настроено на новую ориентацию, поэтому у вас есть один метод с доступом к старой ориентации и новой!

Если я что-то пропустил, и вы уже отказались от возможности использовать этот метод, мои извинения! Кажется странным, что вы создаете и сохраняете переменную для "предыдущей ориентации", когда она предоставляется бесплатно в указанном выше методе.

Надеюсь, что это поможет!

Ответ 4

Используйте это для ориентации пользовательского интерфейса, если вам нужно определить, как вы указываете.

Не уверен, что 100% это правильно, но уходит с головы:

[[[UIApplication sharedApplication] statusBar] orientation]

Ответ 5

Здесь один из способов получить ориентацию, когда приложение загружается, а UIDeviceOrientation - UIDeviceOrientationUnknown. Вы можете посмотреть свойство преобразования повернутого вида.

if(toInterface == UIDeviceOrientationUnknown) {
    CGAffineTransform trans = navigationController.view.transform;
    if(trans.b == 1 && trans.c == -1)
        toInterface = UIDeviceOrientationLandscapeLeft;
    else if(trans.b == -1 && trans.c == 1)
        toInterface = UIDeviceOrientationLandscapeRight;
    else if(trans.a == -1 && trans.d == -1)
        toInterface = UIDeviceOrientationPortraitUpsideDown;
    else
        toInterface = UIDeviceOrientationPortrait;
}

Ответ 6

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

Ответ 7

В ответ на ваш комментарий я подумал, что лучше поставить код здесь, чем в комментарии (хотя действительно Дэниел заслуживает здесь кредита):

в applicationDidFinishLaunching:

[self performSelector:@selector(getOriented) withObject:nil afterDelay:0.0f];

Тогда вам нужен только способ вызова:

- (void) getOriented 
{ 
   UIDeviceOrientation orientation = [[UIDevice currentDevice] orientation];
   // save orientation somewhere
}