UITabBarController, MoreNavigationController e o Santo Graal da rotação de dispositivos

ATUALIZAÇÃO: Veja minha resposta a essa pergunta primeiro. Isso parece ser um bug. Um caso de teste mínimo foi criado e um relatório foi arquivado na Apple. (Corrigido como do iPhone OS 3.1.)

Aqui está um quebra-cabeças do "Estou tão perto!" departamento.

Eu tenho um aplicativo para iPhone baseado em barra de guias. Cada guia apresenta umUINavigationController com os suspeitos usuais (barra de navegação, visão de tabela ... que por sua vez pode levar a outro VC, etc.).

Agora, um desses VCs de nível inferior deve ser usado em portaite modos paisagem. Mas tem um problema. Nossos VC favoráveis ​​à paisagemshouldAutorotateToInterfaceOrientation: não será chamado out-of-the-box! O que fazer?

Aqui está o que fazemos. No meu Tab Bar Controller, que implementei em seu próprio arquivo, tenho isto:

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
     return [self.selectedViewController shouldAutorotateToInterfaceOrientation:interfaceOrientation];
}

Isso acaba propagando a solicitação para o meu VC amigo do ambiente, que também responde a essa mensagem. Todos os meus outros VCs não implementam este método, então eles simplesmente seguem a orientação de retrato padrão.

Problema resolvido!!! Yay!

Bem,não é bem assim. :(

Parece que as coisas não correm tão bem quando o meu VC amigo do ambiente é invocado a partir das profundezas do controlador da barra de abasMaisNavigationController.

Eu decidi comparar / contrastar entre um VC chamado de dentro de um dosprimeiros quatro Barra de abasUINavigationControllers ... e esse mesmo VC chamado de dentro doMaisNavigationController. Isso vai ser um pouco super detalhado, então fique comigo. Espero que a jogada por jogada seja útil para investigar as coisas.

Quando o aplicativo é carregado, há várias chamadas iniciais para o método shouldAutorotate ... do controlador da barra de guias. Nestes primeiros casos,selectedViewController é nulo. No entanto, eventualmente terminamos de carregar, o item da guia inicial é selecionado e tudo está bem.

Certo. Primeiro, vamos escolher um dos quatro primeiros itens da barra de abas e detalhar o nosso VC.

Escolheremos o terceiro item de barra de navegação, então esse é o terceiro controlador de navegação. Nós detalhamos nosso VC que suporta a rotação. Uma inspeção rápida confirma que o pai é de fato o terceiro controlador de navegação da lista de controladores de visualização da nossa barra de guias. Boa!

Vamos girar o dispositivo. O controlador da barra de abas é solicitado a se auto-rotacionar (veja o código acima). Observamos queselectedViewController é também o terceiro controlador de nav, além dos controladores de visualização visível e superior do controlador de navegação, ambos configurados para o nosso confiável VC que suporta rotação.

Assim, o controlador da barra de guias encaminharáshouldAutorotate mensagem para o terceiro controlador de nav ... mas nosso VC de rotação amigável recebe a mensagem. (Eu não estou fazendo nada de especial aqui. Talvez o VC desejado receba a mensagem porque é o VC superior e / ou visível?) Em qualquer caso, nós giramos para a paisagem, as coisas são redimensionadas e tudo está bem. "Grande sucesso!"

Agora vamos apertar o botão de voltar e abrir a pilha VC, deixando o modo paisagem no processo. O controlador da barra de guias é consultado novamente.

Tempo para um pouco de lado aqui. otopViewController para o nosso controlador nav ainda é aquele VC de rotação amigável, masvisibleViewController está agora definido paraUISnapshotModalViewController! Heh Nunca vi isso antes ... masErica Sadun tem. Parece que é para "controladores de visão desaparecendo" (que neste caso é certamente verdade - está desaparecendo bem).

Conforme eu continuo avançando, o VC visível fica como Snapshot, mas o topo VC eventualmente muda para o próximo VC na pilha, já que meu VC especial acabou. Justo.

assimisso é o cenário em que tudo funciona bem.

Agora vamos tentar o mesmo teste, só que desta vez vamos aoMaisNavigationController (o item da barra de guias Mais) e vá até a mesma classe VC de antes. No meu caso, é a 7ª na lista de VC do controlador da barra de guias.

Entramos no VC com reconhecimento de rotação e ... dessa vez é solicitado que ele girediretamente! O Tab Bar Controller énão pediu permissão para rodar. Hmm.

Uma verificação rápida do pai VC mostra que é umMaisNavigationController. OK, isso faz sentido.

Agora vamos tentar rodar o dispositivo.NADA É CHAMADA. Nenhum dos nossos pontos de parada é atingido. Não no nosso VC. Não no nosso controlador de barra de abas. (Hã?!?!)

O-kaaaay Vamos estourar a pilha, voltar para o mesmo VC e tentar girar novamente. Esquisito. AGORA recebemos uma chamada no Controlador de Barra de Guias pedindo permissão de autorotação. Aqui, o Controlador selecionado é o nosso confiável controlador Nav (# 7), mas desta vezvisibleViewController etopViewController estáSET TO NIL!

Uma vez que continuamos a partir daqui, uma misteriosa mensagem aparece no console do depurador:

Usando animação de rotação de dois estágios. Para usar a animação de estágio único mais suave, esse aplicativo deve remover implementações de método de dois estágios.

Misterioso porqueEu não estou usando animação de rotação de dois estágios! NãoSegundo tempo variantes de método estão em jogo em qualquer lugar no meu código-fonte.

Infelizmente, meu VC com reconhecimento de rotação nunca é informado de que a rotação está ocorrendo (mesmo que a rotação ocorra na tela), então é claro que minha visão está toda arruinada como resultado. Caos e tristeza acontecem. :(

Nós não vamos nos incomodar em estourar a pilha neste momento.

Eu acho que o doc View Controller sugere o possível problema:

Se você deseja executar animações personalizadas durante uma alteração de orientação, você pode fazer isso de duas maneiras. As alterações de orientação costumavam ocorrer em duas etapas, com notificações ocorrendo nos pontos inicial, intermediário e final da rotação. No entanto, no iPhone OS 3.0, foi adicionado suporte para executar alterações de orientação em uma etapa. Usando uma orientação de uma etapa, a mudança tende a ser mais rápida do que o processo mais antigo de duas etapas e é geralmente recomendada para qualquer novo código.

Eu me pergunto seMaisNavigationController ainda está respondendo ao processo de duas etapas e, assim, está desarmando qualquer tentativa de usar o processo de uma etapa? Observe que, se você responder às mensagens em duas etapas, a variante de uma etapa não funcionará (novamente, de acordo com os documentos). Eu não estou respondendo a eles, mas eu tenho uma suspeita de algo nos bastidores IS.

Na verdade, se eu comentar o método de etapa única e tentar responder awillAnimateSecondHalfOfRotationFromInterfaceOrientation: duration:, EUFaz pegue o memorando! Mas ainda não sai da pilha com muita clareza (em termos visuais). Ainda mais estranho:willAnimateFirstHalfOfRotationFromInterfaceOrientation: duração: NÃO é chamado, mesmo quando tentei fazer uma chamada para si mesmo (usando a mensagem FirstHalf) emshouldAutorotateToInterfaceOrientation:. Ele retorna imediatamente durante um traço, como se eu nunca tivesse definido isso. Suspiro.

Então esse é o play-by-play.

Em resumo, temqualquer um manipulou com sucesso a rotação de dispositivo de uma etapa para um VC chamado de dentro de um Controlador de Barra de Tabas MoreNavigationController? Mentes inquiridoras querem saber!

questionAnswers(3)

yourAnswerToTheQuestion