Контроллер представления не получает -shouldAutorotateToInterfaceOrientation: сообщения при второй загрузке?

У меня есть UIViewController, который я использую для управления «всплывающим» представлением для просмотра изображений в моем приложении. Он поддерживает авторотацию, так как автоматически изменяет размер изображения, чтобы оно соответствовало размеру независимо от ориентации. Это работает отлично, но только в первый раз, когда я инициализирую и отображаю контроллер представления. Когда он закрывается, я удаляю UIView из моей иерархии представлений и освобождаю контроллер представления, но в следующий раз, когда я создаю его и добавляю в свою иерархию представлений, он перестает получать сообщения -shouldAutorotateToInterfaceOrientation при повороте телефона.

Вот как я создаю и отображаю его:

popupVC = [[PopupVC alloc] init];
[popupVC viewWillAppear:NO];
[[[UIApplication sharedApplication] keyWindow] addSubview:popupVC.view];
[popupVC viewDidAppear:NO];

вот как я удаляю / отпускаю его, когда он закончен:

[popupVC viewWillDisappear:NO];
[popupVC.view removeFromSuperview];
[popupVC viewDidDisappear:NO];
[popupVC release];
popupVC = nil;

Я пробовал перебирать [[UIApplication sharedApplication] keyWindow] подпредставления, чтобы увидеть, не находится ли мое всплывающее окно наверху, но это всегда так. И каждый раз у него другой адрес, поэтому я знаю, что это другой экземпляр класса контроллера представления.

По запросу, вот полный метод loadView из PopupVC:

- (void)loadView {

    UIView *myView = [[UIView alloc] initWithFrame:[UIScreen mainScreen].applicationFrame];
    myView.backgroundColor = self.overlayColor;
    myView.autoresizesSubviews = NO;
    myView.hidden = YES;
    myView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
    self.view = myView;
    [myView release];

    _isVisible = NO;

    UIView *myMaskView = [[UIView alloc] initWithFrame:self.view.bounds];
    myMaskView.backgroundColor = [UIColor clearColor];
    myMaskView.clipsToBounds = YES;
    myMaskView.hidden = YES;
    myMaskView.autoresizesSubviews = NO;
    myMaskView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
    [self.view addSubview:myMaskView];
    self.imageMaskView = myMaskView;
    [myMaskView release];

    UIImageView *myImageView = [[UIImageView alloc] initWithFrame:CGRectZero];
    myImageView.center = self.view.center;
    myImageView.hidden = NO;
    myImageView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleHeight;
    [self.imageMaskView addSubview:myImageView];
    self.imageView = myImageView;
    [myImageView release];

    UIButton *myImageButton = [UIButton buttonWithType:UIButtonTypeCustom];
    myImageButton.frame = self.view.frame;
    myImageButton.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleHeight;
    [myImageButton addTarget:self action:@selector(clickImage:) forControlEvents:UIControlEventTouchUpInside];
    [self.imageMaskView addSubview:myImageButton];
    self.imageButton = myImageButton;

    UIActivityIndicatorView *myActivityView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
    myActivityView.hidden = YES;
    [self.view addSubview:myActivityView];
    myActivityView.center = self.view.center;
    self.activityView = myActivityView;
    [myActivityView release];
}

person pix0r    schedule 30.09.2009    source источник
comment
Когда вы настраиваете контроллер представления? Кроме того, я не считаю, что вам нужно явно вызывать viewWillAppear:, если все дело не в том, чтобы предотвратить анимацию.   -  person G Gordon Worley III    schedule 30.09.2009
comment
Я установил его в UITableViewDelegate методе, когда пользователь выбирает изображение для показа. Мой PopupVC -loadView метод настраивает представление и используемые им подпредставления. У меня появилась привычка явно звонить -viewWillAppear: после того, как я обнаружил, что мои UITabBarController не работают должным образом, если вы не отправите им сообщение ... просто привычка, я думаю.   -  person pix0r    schedule 30.09.2009
comment
вам не следует вызывать эти методы viewWillAppear / viewDidAppear самостоятельно. Я думаю, вам нужно переосмыслить, как вы инициализируете и очищаете всплывающий VC.   -  person Ben Scheirman    schedule 08.10.2009


Ответы (3)


Обработчик shouldAutorotateToInterfaceOrientation - не то место, где пользовательский код реагирует на события вращения. Его цель - просто сообщить ОС, что ваш контроллер представления может вращаться. Если вы хотите иметь собственный код для обработки событий вращения, вы должны игнорировать - didRotateFromInterfaceOrientation или один из других подобных методов обратного вызова в зависимости от ваших потребностей:

  • willRotateToInterfaceOrientation:duration:
  • willAnimateRotationToInterfaceOrientation:duration:
  • didRotateFromInterfaceOrientation:
  • willAnimateFirstHalfOfRotationToInterfaceOrientation:duration:
  • didAnimateFirstHalfOfRotationToInterfaceOrientation:
  • willAnimateSecondHalfOfRotationFromInterfaceOrientation:duration:

См.

person Jason Jenkins    schedule 30.09.2009
comment
Хороший момент - хотя я здесь не отвечаю на событие, я неправильно отлаживаю его. Спасибо что подметил это. - person pix0r; 01.10.2009
comment
Хотя теперь, когда я смотрю, у меня есть отладочный код в -didRotateFromInterfaceOrientation:, и он тоже не запускается. - person pix0r; 01.10.2009
comment
Как насчет того, чтобы ваш контроллер представления переопределил canBecomeFirstResponder, чтобы вернуть ДА, выполните [self becomeFirstResponder] в viewDidAppear:animated и соответствующий [self resignFirstResponder] в viewWillDisappear:animated. Это имеет значение? - person Jason Jenkins; 01.10.2009
comment
К сожалению, нет - мой контроллер представления никогда не получает -canBecomeFirstResponder:. (Но это звучало многообещающе!) - person pix0r; 01.10.2009
comment
Как создается ваше представление контроллеров представления? Можете ли вы поделиться кодом в методе loadView вашего PopupVC? Кроме того, ваше представление владеет всем экраном или это своего рода модальное всплывающее окно, перекрывающее другое представление? - person Jason Jenkins; 08.10.2009
comment
Вид покрывает весь экран. Я добавил метод loadView из PopupVC (см. Исходный вопрос). - person pix0r; 09.10.2009

Думаю, это может быть ошибка новой ОС 3.0. Обходным путем для этого было бы использование NSNotificationCenter после включения beginGeneratingDeviceOrientationNotifications.

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

    [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receivedRotate:) name:UIDeviceOrientationDidChangeNotification object:nil]; 
}

-(void) receivedRotate: (NSNotification *) notification {
    DebugLog(@"ORIENTATION CHANGE");

    UIDeviceOrientation interfaceOrientation = [[UIDevice currentDevice] orientation];

        if(interfaceOrientation == UIDeviceOrientationPortrait) {
            self.view.transform = CGAffineTransformMakeRotation(degreesToRadian(0));
            self.view.bounds = CGRectMake(0, 0, 320, 480);
        }
        else if(interfaceOrientation == UIDeviceOrientationLandscapeLeft) {
            self.view.transform = CGAffineTransformMakeRotation(degreesToRadian(90));
            self.view.bounds = CGRectMake(0, 0, 480, 320);
        }
        else if(interfaceOrientation == UIDeviceOrientationLandscapeRight) {
            self.view.transform = CGAffineTransformMakeRotation(degreesToRadian(-90));
            self.view.bounds = CGRectMake(0, 0, 480, 320);
        }
}
person Jonathan Reyes    schedule 15.10.2009

Моя проблема в том, что я получаю событие вращения для моего rootViewController, но как только я запускаю свой второй viewController, он не будет получать никаких сигналов, кроме движения (встряхивания) и касания. Это та же проблема, что и в исходном сообщении - это определенно похоже ??

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

person mobibob    schedule 26.10.2009