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

Обнаружение изменения ориентации iOS мгновенно

У меня есть игра, в которой ориентация устройства влияет на состояние игры. Пользователь должен быстро переключаться между пейзажными, портретными и обратными ориентациями ландшафта. До сих пор я регистрировал игру для уведомлений о ориентации через:

[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];

Но он слишком медленный - кажется, существует примерно вторая задержка между поворотом телефона и фактическим увольнением уведомления. Мне нужен способ МГНОВЕННО обнаруживать изменения в ориентации устройства. Я пробовал экспериментировать с гироскопом, но я еще не достаточно знаком с ним, чтобы узнать, действительно ли это решение, которое я ищу.

4b9b3361

Ответ 1

Эта задержка, о которой вы говорите, на самом деле является фильтром для предотвращения ложных (нежелательных) уведомлений об изменении ориентации.

Для мгновенного распознавания изменения ориентации устройства вам просто нужно будет самостоятельно контролировать акселерометр.

Акселерометр измеряет ускорение (с учетом силы тяжести) во всех трех осях, поэтому у вас не должно возникнуть никаких проблем при определении фактической ориентации.

Некоторый код для начала работы с акселерометром можно найти здесь:

Как сделать приложение для iPhone - Часть 5: Акселерометр

И этот приятный блог охватывает математическую часть:

Использование акселерометра

Ответ 2

Добавить уведомитель в функции viewWillAppear

-(void)viewWillAppear:(BOOL)animated{
  [super viewWillAppear:animated];
  [[NSNotificationCenter defaultCenter] addObserver:self  selector:@selector(orientationChanged:)    name:UIDeviceOrientationDidChangeNotification  object:nil];
}

Изменение ориентации уведомляет эту функцию

- (void)orientationChanged:(NSNotification *)notification{
   [self adjustViewsForOrientation:[[UIApplication sharedApplication] statusBarOrientation]];
}

который в свою очередь вызывает эту функцию, в которой обрабатывается ориентация кадра moviePlayerController

- (void) adjustViewsForOrientation:(UIInterfaceOrientation) orientation {

    switch (orientation)
    {
        case UIInterfaceOrientationPortrait:
        case UIInterfaceOrientationPortraitUpsideDown:
        { 
        //load the portrait view    
        }

            break;
        case UIInterfaceOrientationLandscapeLeft:
        case UIInterfaceOrientationLandscapeRight:
        {
        //load the landscape view 
        }
            break;
        case UIInterfaceOrientationUnknown:break;
    }
}

в viewDidDisappear удалить уведомление

-(void)viewDidDisappear:(BOOL)animated{
   [super viewDidDisappear:animated];
   [[NSNotificationCenter defaultCenter]removeObserver:self name:UIDeviceOrientationDidChangeNotification object:nil];
}

Я думаю, что это самый быстрый и может изменить вид в зависимости от ориентации

Ответ 3

Почему вы не использовали

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation

?

Или вы можете использовать этот

-(void) willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration

Или это

-(void) didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation

Надеюсь, что это будет полезно)

Ответ 4

Для моей обработки дела UIDeviceOrientationDidChangeNotification не было хорошего решения, так как оно называется более частым, а UIDeviceOrientation не всегда равно UIInterfaceOrientation из-за (FaceDown, FaceUp).

Я обрабатываю его с помощью UIApplicationDidChangeStatusBarOrientationNotification:

//To add the notification
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didChangeOrientation:)

//to remove the
[[NSNotificationCenter defaultCenter]removeObserver:self name:UIDeviceOrientationDidChangeNotification object:nil];

 ...

- (void)didChangeOrientation:(NSNotification *)notification
{
    UIInterfaceOrientation orientation = [UIApplication sharedApplication].statusBarOrientation;

    if (UIInterfaceOrientationIsLandscape(orientation)) {
        NSLog(@"Landscape");
    }
    else {
        NSLog(@"Portrait");
    }
}

Ответ 5

Попробуйте внести изменения:

- (void) viewWillLayoutSubviews {}

Код будет запускаться при каждом изменении ориентации, так как снова будут отображаться подпрограммы.

Ответ 6

@vimal ответ не предоставил мне решение. Кажется, ориентация - это не текущая ориентация, а предыдущая ориентация. Чтобы исправить это, я использую [[UIDevice currentDevice] orientation]

- (void)orientationChanged:(NSNotification *)notification{
    [self adjustViewsForOrientation:[[UIDevice currentDevice] orientation]];
}

Тогда

- (void) adjustViewsForOrientation:(UIDeviceOrientation) orientation { ... }

С помощью этого кода я получаю текущую позицию ориентации.