Почему iOS не выполняет автоповорот представления, загруженного из пера после того, как оно было выпущено didReceiveMemoryWarning?

В приложении My iPad активно используется автоповорот. Отлично. Однако я заметил, что если скрытое представление выпускается реализацией по умолчанию didReceiveMemoryWarning (как описано здесь), когда вид перезагружается из пера, и я оказываюсь в альбомной ориентации, он загружает его в портретной ориентации. Это наносит ущерб интерфейсу, пока я не поверну iPad вручную и не заставлю его принять правильную ориентацию.

Я предполагал, что iOS загрузит представление в текущей ориентации; это то, что он делает, когда приложение запускается. Но это не после того, как его выгрузил didReceiveMemoryWarning. Почему нет? И как я могу заставить его это сделать?


person theory    schedule 11.01.2011    source источник
comment
Представление находится вне иерархии представлений (не является подпредставлением представления UIViewController)?   -  person dstnbrkr    schedule 11.01.2011
comment
@dbarker - Нет, на самом деле это основной вид приложения.   -  person theory    schedule 11.01.2011
comment
@dbarker А, но присмотревшись повнимательнее, я вижу, что это подпредставления этого представления, которые не повернуты должным образом. Подвиды, включенные в кончик, правильно повернуты. Вроде, как бы, что-то вроде. Хрм. Что-то может быть не так с моим методом -willAnimateRotationToInterfaceOrientation:duration:. Может быть, он не вызывается, потому что вращение не анимировано?   -  person theory    schedule 11.01.2011
comment
Да, ни -willRotateToInterfaceOrientation:duration:, ни -willAnimateRotationToInterfaceOrientation:duration: не вызываются. Они оба вызываются при запуске приложения…   -  person theory    schedule 11.01.2011
comment
Звучит правильно - обратные вызовы вращения не будут вызываться, когда представление (повторно) загружается. Для представлений, которые не управляются пером, вам нужно будет настроить их вручную в соответствии с ориентацией, которую возвращает UIViewController#interfaceOrientation. Не уверен, но возможно, что перо делает это за кулисами.   -  person dstnbrkr    schedule 11.01.2011
comment
Хрм. В каком методе я должен это сделать? Это уже делается автоматически при запуске, поэтому мне нужно знать, загружается ли представление при запуске.   -  person theory    schedule 12.01.2011
comment
Эта проверка должна происходить в viewDidLoad. Если я правильно понимаю, viewDidLoad всегда ориентирует эти представления в одну сторону, а сообщения will/didRotate исправляют это (при запуске), если это неправильно. Поскольку бывают случаи, когда происходит viewDidLoad, а will/didRotate не отправляются, viewDidLoad должен корректно настроить эти представления для текущей ориентации. Сообщения will/didRotate по-прежнему будут обрабатывать дальнейшие изменения ориентации.   -  person dstnbrkr    schedule 12.01.2011
comment
Да, это то, что я понял; см. ответ ниже. Впрочем, как-то раздражает. Спасибо за помощь!   -  person theory    schedule 12.01.2011


Ответы (2)


Ответ, определенный благодаря указателям из dbarker, заключается в том, что методы вращения контроллера представления, включая -willRotateToInterfaceOrientation:duration: и -willAnimateRotationToInterfaceOrientation:duration:, не будут вызывается, когда представление перезагружается после того, как реализация didReceiveMemoryWarning по умолчанию выгрузила представление. Я понятия не имею, почему при запуске приложения все будет иначе, но у меня есть обходной путь.

Что я сделал, так это установил логическую переменную с именем unloadedByMemoryWarning на YES в didReceiveMemoryWarning, например так:

- (void) didReceiveMemoryWarning {
    unloadedByMemoryWarning = YES;
    [super didReceiveMemoryWarning];
}

Затем, в viewDidLoad, если этот флаг равен true, я устанавливаю его в NO, а затем сам вызываю методы поворота:

if (unloadedByMemoryWarning) {
    unloadedByMemoryWarning = NO;
    [self willRotateToInterfaceOrientation:self.interfaceOrientation duration:0];
    [self willAnimateRotationToInterfaceOrientation:self.interfaceOrientation duration:0];
    [self didRotateFromInterfaceOrientation:self.interfaceOrientation];
}

Немного отстойно, что я должен это делать, но это работает, и теперь я меньше беспокоюсь о том, что iOS убьет меня за использование слишком большого объема памяти.

person theory    schedule 12.01.2011
comment
Я столкнулся с той же проблемой в своем приложении для iPad. Это довольно странное поведение, но ваше решение помогло мне. - person sandy; 09.05.2011
comment
Пробовал это решение, но, к сожалению, оно не работает с моей стороны. Блин... копается - person Kalle; 04.01.2012

  1. Я думаю, что iOS 5 может исправить это.

  2. Для iOS 4.3 мне повезло с другим исправлением. После загрузки из пера:

    [parent.view addSubview:nibView];  
    nibView.frame = parent.view.frame;  
    [nibView setNeedsLayout];  
    

    Если бы это сработало, вы могли бы отказаться от логики unloadedByMemoryWarning, так как безопасно выполнять каждую загрузку. Получил совет и код (в основном) от здесь.

person Clay Bridges    schedule 05.01.2012