Edgesforextendedlayout ios 8


Como remover o preenchimento inesperado no cabeçalho de um UITableView.
Quase toda vez que eu coloco um controlador de navegação, com um controlador de vista de raiz que contém uma visão de tabela, o resultado é uma exibição de tabela com um preenchimento inesperado no cabeçalho dele.
A razão pela qual isso acontece é a propriedade de UIViewController automaticamenteAdjustsScrollViewInsets, que é um valor booleano que indica se o controlador de exibição deve ajustar automaticamente suas inserções de exibição de rolagem. , e defina para SIM.
A propriedade foi introduzida no iOS 7 e, juntamente com as bordasForExtendedLayout, faz com que o efeito agradável da rolagem de conteúdo abaixo de uma barra de navegação translúcida seja possível.
Como corrigi-lo.
Até agora encontrei duas maneiras de resolver esse problema de UI:
Defina automaticamenteAdjustsScrollViewInsets como falso.
Definir o valor automaticAdjustsScrollViewInsets para false resolve o problema.
No Interface Builder, isso pode ser feito soltando a opção "Ajustar a inserção da exibição de rolagem" do controlador de exibição onde a vista da tabela é.
Faça a barra de navegação não translúcida.
Outra opção é tornar a barra de navegação não translúcida. Essa barra de navegação não desencadeia os ajustes das inserções de exibição de rolagem no controlador de exibição.
No Interface Builder, isso pode ser feito soltando a opção "Translúcido" da barra de navegação do controlador de navegação. Eu também achei que a única maneira de realmente selecionar esse componente é através da árvore de hierarquia de exibição à esquerda.
UIViewController contenção.
Uma nota final nas vistas de mesa embutida através da contenção do controlador de exibição. Para evitar o cabeçalho naqueles, precisamos novamente configurar a falsa a propriedade automaticAdjustsScrollViewInsets do controlador de exibição pai.
Isso me pareceu intuitivo ao princípio. Mas se pensarmos sobre o funcionamento do processo de contenção, extraindo a visão da criança e colocando-a no pai, torna-se óbvio que as regras de layout, como AutomaticAdjustsScrollViewInsets do pai, também se aplicam à criança.
Comida para pensamentos.
Existe outra maneira, talvez melhor, de corrigir esse problema? Pode ser evitado, deitando os pontos de vista de forma diferente? Por que o controlador de navegação padrão + controlador de exibição de tabela da biblioteca de componentes do Interface Builder não faz isso? Olhe mais fundo para os mecanismos automaticAdjustsScrollViewInsets e edgesForExtendedLayout.
Jornal técnico da mokagio.
Olá, meu nome é Giovanni, mas na web eu sou o mokagio. Sou engenheiro independente de iOS e estou disponível para trabalho por contrato.
Este lugar é um colecionador de descobertas aleatórias sobre pequenos detalhes do desenvolvimento de software.
Você deve verificar o meu outro blog: mokacoding, onde eu escrevo postagens apropriadas, ao invés de notas aleatórias.

Corrigindo o problema de sobreposição da barra de navegação iOS 7.
Houve um problema que está envolvendo desenvolvedores de iOS desde que as barras de navegação bastante transparentes vieram no iOS 7, algo que quando eu pergunto às pessoas por que isso acontece, eles absolutamente não tem ideia.
Existe uma solução simples que todos estão usando, mas é um hack e muitos desenvolvedores acabaram de usá-lo sem entender o problema.
Coloque isso no seu controlador e, de repente, ele apenas funciona. um pouco. Agora, a barra de navegação não tem como ser transparente, o que derrota o propósito. As visualizações que deveriam estar por trás disso, nossa visão de raiz, e a cor do plano de fundo, que não está sendo exibida.
Honestamente, você pode não se importar, isso pode ser suficiente para você, mas é importante que você ainda entenda o problema, então leia. Se você fez o desenvolvimento da web, isso é como um estouro: oculto no CSS. O trabalho, mas ainda é um tipo de "hack".
Então, o problema é que, quando o quadro da re view estiver configurado, ao contrário do iOS 6, o quadro ainda engloba a área embaixo da barra de navegação.
O que você talvez não tenha percebido, é se um UIScrollView ou uma subclasse como UITableView, é a visão de raiz do seu controlador, ele terá a propriedade contentInset da propriedade definida corretamente, permitindo que o quadro esteja por baixo da barra de navegação, mas a origem real que começa a desenhar é da parte inferior da barra de navegação.
Isso significa que podemos simplesmente resolver o problema da sobreposição da barra de navegação, fazendo com que nossa visão de raiz seja UIScrollView (ou subclasse de), enquanto ainda deixa nossa cor de fundo brilhar.
Você pode fazer sua visão de raiz um UIScrollView definindo o método loadView, onde sua visão de raiz e suas submissões devem estar sendo criadas se você estiver criando suas visualizações de forma programática.
Se você tentar isso, você obterá isso.
Observe o vermelho brilhando através da barra de navegação? Observe que nós estabelecemos a origem da tela azul para ser o canto superior esquerdo? Tudo está bem sentado e funciona como a Apple esperava que usássemos as barras de navegação transparentes.
Isso tem o bônus adicional de nos dar uma maneira mais fácil de expandir nosso layout além da tela, agora, agora que estamos usando uma exibição de rolagem, mas você pode não precisar disso de qualquer maneira, em vez disso, você pode apenas usá-lo como um substituto para UIView que pode ter o conjunto contentInset da sua.
Eu não procurei as diferenças de memória para isso, mas minha expectativa é que seria extremamente mínimo.
Se você quiser saber mais sobre o RubyMotion, confira os meus screencasts em https://motioninmotion. tv/ ou o meu próximo livro RubyMotion for Rails Developers, que está disponível para pré-encomenda agora, sob um modelo de pagamento Pay What You Want, com a parte 1 quase terminada e deve ser lançada em breve.
RubyMotion Adventures - O Blog MotionInMotion.
RubyMotion Adventures - The MotionInMotion Blog info @ fluffyjack.
Tutoriais, dicas, guias e fatos divertidos RubyMotion. Novas postagens em nenhum programa que não sejam "postar frequentemente"

Edgesforextendedlayout ios 8
Obter através da App Store Leia esta publicação em nosso aplicativo!
Explicando a diferença entre automaticAdjustsScrollViewInsets, extendedLayoutIncludesOpaqueBars, edgesForExtendedLayout no iOS7.
Eu tenho lido muito sobre a transição do IOS7 UI.
Não consigo obter o que estas três propriedades automaticamenteAdjustsScrollViewInsets, extendedLayoutIncludesOpaqueBars, edgesForExtendedLayout ??
Por exemplo, estou tentando fazer meus controladores de exibição começar abaixo da barra de status, mas não consigo alcançá-lo.
Começando no iOS7, os controladores de exibição usam o layout de tela inteira por padrão. Ao mesmo tempo, você tem mais controle sobre como ele expõe seus pontos de vista, e isso é feito com essas propriedades:
Basicamente, com esta propriedade, você define quais lados da sua visão podem ser estendidos para cobrir toda a tela. Imagine que você empurre um UIViewController para um UINavigationController. Quando a exibição desse controlador de visualização é estabelecida, ele iniciará onde a barra de navegação termina, mas essa propriedade irá definir quais lados da vista (superior, esquerda, inferior, direita) podem ser estendidos para preencher a tela inteira.
Vamos vê-lo com um exemplo:
Aqui você não está configurando o valor de edgesForExtendedLayout, portanto, o valor padrão é tomado (UIRectEdgeAll), então a exibição amplia seu layout para preencher toda a tela.
Este é o resultado:
Como você pode ver, o fundo vermelho se estende por trás da barra de navegação e da barra de status.
Agora, você vai definir esse valor para UIRectEdgeNone, então você está dizendo ao controlador de exibição para não estender a exibição para cobrir a tela:
Essa propriedade é usada quando sua exibição é UIScrollView ou similar, como um UITableView. Você quer que sua mesa comece onde a barra de navegação termina, porque você não verá todo o conteúdo se não, mas ao mesmo tempo você deseja que sua mesa cubra toda a tela quando se desloca. Nesse caso, a definição de bordasForExtendedLayout para Nenhum não funcionará porque sua tabela começará a rolar onde a barra de navegação termina e não vai atrasá-la.
Aqui é onde esta propriedade é útil, se você deixar o controlador de exibição ajustar automaticamente as inserções (configurando esta propriedade para SIM, também o valor padrão), ele irá adicionar inserções no topo da tabela, então a tabela começará onde a navegação A barra termina, mas o pergaminho cobrirá toda a tela.
É quando é definido como NÃO:
E SIM (por padrão):
Em ambos os casos, a tabela se desliza para trás da barra de navegação, mas no segundo caso (SIM), ele irá começar por baixo da barra de navegação.
Esse valor é apenas uma adição aos anteriores. Por padrão, esse parâmetro é definido como NO. Se a barra de status for opaca, as visualizações não serão estendidas para incluir a barra de status, mesmo se você estender sua visão para cobri-la (edgeForExtendedLayout para UIRectEdgeAll).
Se você definir o valor como SIM, isso permitirá que a visão vá novamente debaixo da barra de status.
Se algo não estiver claro, escreva um comentário e vou responder.
Como o iOS sabe o que o UIScrollView usa?
O iOS agarra a primeira sub-visualização na visão do ViewController, a do índice 0, e se é uma subclasse do UIScrollView, então aplica as propriedades explicadas a ela.
Claro, isso significa que o UITableViewController funciona por padrão (uma vez que o UITableView é a primeira visualização).
Não tenho certeza se você está usando storyboards, mas se você for, para fazer seus controladores de exibição começarem abaixo da barra de status (e acima da barra inferior):
Selecione o controlador de visualização no IB, no inspetor de atributos, desmarque 'Extendir bordas - Em barras superiores' e 'Ampliar bordas - em barras inferiores'.
Estou usando storyboards e usando o conselho acima, no entanto, não sabia exatamente como implementá-lo. Abaixo está um pequeno exemplo no modo como ele esclareceu o problema colocando a solução recomendada no ViewController.
Meu Problema: Auto Adjust definido como true por padrão causando uma diferença entre o design do storyboard e o simulador.
Resolvido: Código acima aplicado, desligando o ajuste automático.
Resolvi esse problema ao adicionar esta linha, mas meu problema estava relacionado a um UIView, não ao UIScrollView.
Basta ter em mente que a propriedade AutomaticAdjustsScrollViewInsets funciona somente se algum tipo de exibição de rolagem (exibição de tabela, exibição de coleção) for.
A visão do VC, ou Primeira subvisão desta visão.
Outro sugerido, que ele funciona, mesmo que seja a primeira subvisão, mas existem outras visualizações de rolagem na hierarquia de exibição.
EDITAR (extensão DIY)
Se você quiser um comportamento semelhante mesmo que não possa cumprir essas condições (por exemplo, você tem uma imagem de fundo abaixo da visualização de rolagem), você pode ajustar manualmente as inserções de exibição de rolagem. Mas, por favor, não configurá-lo como constante, como 44 ou 64 ou mesmo 20 como muitos sugerem em torno de SO. Você não pode conhecer o tamanho de todos. Pode haver notificação de incall / gps / audio, a barra de navegação não precisa estar sempre 44 pts, etc.
Eu acho que a melhor solução é usar o comprimento layoutGuide em didLayoutSubviews:
Você pode usar o guia bottomLayout da mesma maneira.

iOS7, nós temos um problema.
Hoje é o dia, iOS7 lança para todos os iPhones & amp; iPads. O que isso significa para nós desenvolvedores? Muito trabalho, isso é o que. Ao contrário de outras transições iOS5 - & gt; iOS6, todos os aplicativos anteriores & # 8220; apenas trabalhou & # 8221; mas esta versão é a maior mudança desde o iOS 3.0. Aproximadamente cerca de 90% dos aplicativos testados estão tendo problemas para executar no iOS7, esses problemas variam de aplicativos que falham no lançamento para os rótulos alinhados incorretamente com a barra de status nas principais visualizações de problemas.
Deixe-nos dar uma olhada no problema mais comum que os desenvolvedores estão tendo, a barra de status.
Barra de status aparece em minha exibição.
Você pode conseguir isso implementando nova propriedade chamada edgeForExtendedLayout no iOS7 SDK. Adicione o seguinte código para conseguir isso,
Você precisa adicionar o acima em seu método - (void) viewDidLoad.
O iOS 7 traz várias mudanças na forma como você define e personaliza a aparência de sua IU. As mudanças no layout do controle de exibição, cor de matiz e fonte afetam todos os objetos UIKit em seu aplicativo. Além disso, os aprimoramentos das API do reconhecimento de gestos oferecem um controle mais fino sobre as interações gestuais.
No iOS 7, os controladores de visualização usam o layout em tela cheia. Ao mesmo tempo, o iOS 7 dá-lhe um controle mais detalhado na forma como um controlador de visualização apresenta suas visualizações. Em particular, o conceito de layout em tela cheia foi refinado para permitir que um controlador de visualização especifique o layout de cada extremidade de sua exibição.
A propriedade wantFullScreenLayout view controller está obsoleta no iOS 7. Se você especificar atualmente wantFullScreenLayout = NO, o controlador de exibição pode exibir seu conteúdo em um local de tela inesperado quando ele é executado no iOS 7.
Para ajustar como um controlador de visualização apresenta suas visualizações, o UIViewController fornece as seguintes propriedades:
A propriedade edgesForExtendedLayout usa o tipo UIRectEdge, que especifica cada uma das quatro bordas de um retângulo, além de especificar nenhum e todos. Use edgeForExtendedLayout para especificar quais bordas de uma vista devem ser estendidas, independentemente da translucidez da barra. Por padrão, o valor dessa propriedade é UIRectEdgeAll.
Se o seu projeto usa barras opacas, refine edgesForExtendedLayout, definindo também a propriedade extendedLayoutIncludesOpaqueBars como NO. (O valor padrão de extendedLayoutIncludesOpaqueBars é NO).
Se você não deseja que as configurações de conteúdo de uma exibição de rolagem sejam ajustadas automaticamente, defina automaticamenteAdjustsScrollViewInsets como NO. (O valor padrão de automaticAdjustsScrollViewInsets é YES).
As propriedades topLayoutGuide e bottomLayoutGuide indicam a localização das bordas da barra superior ou inferior na vista do controlador de visualização. Se as barras devem se sobrepor à parte superior ou inferior de uma vista, você pode usar o Interface Builder para posicionar a vista em relação à barra, criando restrições na parte inferior do TopLayoutGuide ou no topo do bottomLayoutGuide. (Se nenhuma barra deve sobrepor-se à vista, a parte inferior do TopLayoutGuide é a mesma que a parte superior da vista e a parte superior do bottomLayoutGuide é a mesma que a parte inferior da vista.) Ambas as propriedades são preguiçosamente criadas quando solicitado.

Edgesforextendedlayout ios 8
Os controladores de visualização simplificam o gerenciamento de vistas para muitas aplicações iOS. Cada controlador de exibição possui uma hierarquia de visualizações, que apresenta um elemento completo de uma interface unificada. Os controladores de visualização permitem que você crie aplicativos que centralizem muitas tarefas, incluindo mudanças de orientação e respondendo às ações do usuário. Este capítulo analisa o uso de classes baseadas no view controller & ndash e como aplicá-las a situações do mundo real para cenários de design de iPhone / iPod e iPad.
Como o próprio nome sugere, os controladores de visão fornecem o componente do controlador do Modelo e padrão de projeto do iOS & rsquo; s e o padrão de design do controlador. Cada controlador de visualização gerencia um conjunto de visualizações que compõem um único componente de interface de usuário dentro de um aplicativo. Os controladores de visualização coordenam o carregamento e a aparência da visualização, além de participar na resposta às interações do usuário.
Os controladores de visualização também se harmonizam com o dispositivo e o sistema operacional subjacente. Quando um usuário roda o dispositivo, por exemplo, o controlador de visualização pode atualizar suas visualizações & rsquo; layout. Quando o sistema operacional encontra um cenário de pouca memória, os controladores respondem aos avisos de memória.
Em suma, os controladores de visualização fornecem gerenciamento central. Eles negociam com uma variedade de requisitos de desenvolvimento ortogonal provenientes de visualizações, modelos, iOS e o próprio dispositivo.
Os controladores de visão também centralizam as metáforas de apresentação. A capacidade de controladores de exibição de camada em contêiner estende o paradigma a projetos personalizados interessantes. Os estilos mais comuns de controladores de exibição pai / filho fornecidos pelo sistema incluem controladores de navegação que permitem que os usuários movam sua atenção de vista para exibição, controladores de exibição de página que apresentam livros virtuais, controladores de tabulações que oferecem acesso de botão para vários controladores filho e vista dividida controladores que oferecem apresentações de lista principal / detalhe.
Ver controladores não são exibidos. São classes sem representação visual, exceto através das visualizações que elas gerenciam. Os controladores de visualização ajudam suas visualizações ao vivo em um ambiente de design de aplicativos maior.
O iOS SDK oferece muitas classes de controle de exibição. Essas classes variam de geral a específico. Aqui, um guia rápido para um subconjunto dos controladores de exibição que você encontrará durante a construção das interfaces de aplicativos iOS.
UIViewController é a classe pai para controladores de visualização e aquele que você usa para gerenciar suas visualizações primárias. É o cavalo-de-obra dos controladores de visualização. Você pode gastar uma grande parte do seu tempo personalizando subclasses desta classe. A classe UIViewController básica gerencia a vida de cada visão primária do início ao fim e leva em consideração as mudanças que a visão deve reagir ao longo do caminho.
As instâncias do UIViewController são responsáveis ​​por configurar como uma visão é exibida e quais submissões ela é exibida. Muitas vezes eles dependem de carregar essa informação de arquivos XIB ou storyboard. Os métodos de instância permitem que você crie manualmente o layout de exibição no código (loadView) ou adicione o comportamento depois que uma visualização finaliza o carregamento (viewDidLoad).
Reagir às visualizações exibidas ou descartadas é outro trabalho que controla os controladores. Estas são as realidades de pertencer a uma aplicação maior. Métodos como viewWillAppear: e viewWillDisappear: permitem concluir qualquer contabilidade associada ao gerenciamento de vistas. Você pode pré-carregar dados em antecipação a ser apresentado ou limpo uma vez que uma visualização não será exibida na tela.
Cada uma das tarefas mencionadas aqui especifica como uma visão se encaixa em uma aplicação envolvente. O UIViewController medeia entre visualizações e essas demandas externas, permitindo que a visão se alterasse para atender a essas necessidades.
Como o nome sugere, os controladores de navegação permitem que você perfile e desça através de hierarquias de exibição baseadas em árvore, que é uma importante estratégia de projeto de interface primária em membros menores da família de dispositivos iOS e um suporte em tablets. Os controladores de navegação criam as barras de navegação translúcidas que aparecem no topo de muitas aplicações iOS padrão.
Os controladores de navegação permitem que você coloque novas visualizações no lugar em uma pilha armazenada e gere automaticamente os botões Voltar que mostram o título do controlador de exibição de chamada. Todos os controladores de navegação usam um & ldquo; root & rdquo; veja o controlador para estabelecer a parte superior de sua árvore de navegação, deixando esses botões Voltar levá-lo de volta à visualização principal. Em tablets, você pode usar uma interface baseada no controlador de navegação e ndash para trabalhar com itens de menu baseados na barra e ndash, para apresentar apresentações de popover ou para se integrar com instâncias UISplitViewController para uma experiência de apresentação mestre / detalhada.
A entrega de responsabilidade a um controlador de navegação permite focar o trabalho de design na criação de telas de controle de visualização individuais. Você não precisa se preocupar com detalhes de navegação específicos além de dizer ao controlador de navegação que vê para passar para o próximo. A pilha de histórico e os botões de navegação são manipulados para você.
A classe UITabBarController permite que você controle apresentações paralelas em sua aplicação. Estas são como estações em um rádio. Uma barra de guia ajuda os usuários a selecionar qual controlador de exibição para & ldquo; sintonizar, & rdquo; sem haver uma hierarquia de navegação específica. Cada mundo paralelo opera de forma independente, e cada um pode ter sua própria hierarquia de navegação. Você cria o controlador de visualização ou o controlador de navegação que habita cada guia e o Cocoa Touch manipula os detalhes de exibição múltipla.
Por exemplo, quando as instâncias da barra de tabulação oferecem mais de um certo número de opções de controle de exibição de cada vez (cinco na família de dispositivos iPhone, mais em tablets), os usuários podem personalizá-las através do More & gt; Edite a tela. O Mais & gt; A tela de edição permite que os usuários arrastem seus controladores favoritos para a barra de botões na parte inferior da tela. Não há programação extra envolvida. Você ganha abas editáveis ​​de graça. Tudo o que você precisa fazer é solicitá-los através da propriedade customizableViewControllers.
Para a utilização em aplicações de tablets, a classe UISplitViewController oferece uma maneira de encapsular um conjunto persistente de dados (normalmente uma tabela) e associar esses dados com uma apresentação detalhada. Você pode ver vistas divididas em ação na aplicação de correio eletrônico do iPad. Quando usado na orientação horizontal, uma lista de mensagens aparece à esquerda; O conteúdo da mensagem individual aparece à direita. A visualização de detalhes (o conteúdo da mensagem no Correio) à direita está subordinada à vista principal (lista de mensagens do Mail & rsquo; s) à esquerda. Toque uma mensagem atualiza a vista do lado direito com seus conteúdos.
Na orientação vertical, a vista principal está normalmente escondida. É acessado através de um popover, que é alcançado tocando no botão esquerdo da barra superior da vista dividida & rsquo; s ou através de um gesto de deslize (no iOS 5.1 e posterior).
Como controladores de navegação, controladores de exibição de tabulação e controladores de exibição dividida, os controladores de exibição de página são contêineres para outros controladores de exibição. Eles gerenciam páginas de conteúdo usando uma apresentação de curling de página semelhante a um livro ou um estilo de rolagem. Ao usar o estilo de ondulação da página, você define o livro & rsquo; s & ldquo; spine, & rdquo; normalmente ao longo do lado esquerdo ou superior da vista. Crie seu & ldquo; book & rdquo; adicionando controles de exibição de conteúdo individuais. Cada & ldquo; página & rdquo; transições para a próxima usando curvas de página ou panelas.
Especificamente para tablets, os controladores de popover criam visões transitórias que aparecem sobre outros conteúdos de interface existentes. Esses controladores apresentam informações sem assumir a tela inteira, da maneira que as vistas modais normalmente fazem. Os popovers geralmente são invocados tocando um item de botão de barra na interface (embora possam ser criados usando outras técnicas de interação) e são descartados, interagindo com o conteúdo que eles apresentam ou tocando fora de sua visão principal.
Popovers são preenchidos com instâncias do controlador de exibição. Crie o controlador de visualização e atribua-o como propriedade contentViewController do popover & rsquo; s antes de apresentar o popover. Isso permite que popovers apresente qualquer tipo de material que você possa projetar em um controlador de exibição padrão, oferecendo excepcional flexibilidade de programação.
Começando no iOS 5, você pode subclasse UINavigationBar e incorporar apresentações personalizadas nas interfaces de navegação do seu aplicativo. Use o initWithNavigationBarClass: toolbarClass: método de inicialização.
Desenvolvendo com controladores de navegação e vistas divididas.
A classe UINavigationController oferece uma das formas mais importantes de gerenciar interfaces em um dispositivo com espaço de tela limitado. Ele cria uma maneira para os usuários navegar para cima e para baixo uma hierarquia de apresentações de interface para criar uma GUI virtual que é muito maior do que o dispositivo. Os controladores de navegação dobram suas GUIs em um esquema baseado em árvores. Os usuários viajam através desse esquema usando botões e escolhas que os transportam ao redor da árvore. Você vê os controladores de navegação no aplicativo Contatos e nas Configurações, onde as seleções levam a novas telas e os botões Voltar movem para as anteriores.
Vários elementos GUI padrão revelam o uso de controladores de navegação em aplicativos, como mostrado na Figura 7-1 (esquerda). Estas incluem as suas grandes barras de navegação que aparecem na parte superior de cada tela, o botão de apontar para trás no canto superior esquerdo que aparece quando o usuário perfura as hierarquias e os botões de opções no canto superior direito que oferecem outras funcionalidades do aplicativo, como a edição. Muitos aplicativos de controle de navegação são construídos em torno de listas de rolagem, onde os elementos de uma lista levam a novas telas, indicadas pelo indicador de divulgação (chevron cinza) e o botão de divulgação detalhada (envolvido i) encontrado no lado direito de cada célula da tabela.
Figura 7-1 O controlador de navegação do iPhone (esquerdo) usa chevrons cinza para indicar que as visualizações de detalhes serão pressionadas na tela quando seus pais forem selecionados. No iPad (à direita), os controladores de visualização dividida usam toda a tela, separando os elementos de navegação das apresentações detalhadas.
O iPad, com seu tamanho de tela grande, não requer o tipo de atalhos que economizam espaço que os controladores de navegação utilizam em dispositivos de família iPhone. As aplicações Tablet podem usar controladores de navegação diretamente, mas o UISplitViewController mostrado na Figura 7-1 (direita) oferece uma apresentação que é mais adequada para o dispositivo mais expansivo.
Observe as diferenças entre a implementação do iPhone à esquerda e a implementação do iPad à direita da Figura 7-1. O controlador de vista dividida do iPad & rsquo; s não contém chevrons. Quando os itens são digitados, seus dados aparecem na mesma tela, usando a grande área de detalhes do lado direito. O iPhone, sem esse espaço, apresenta chevrons que indicam que novas visualizações serão exibidas na tela. Cada abordagem leva em consideração o design específico do dispositivo na sua apresentação.
As telas iPhone-family e iPad Inbox usam elementos similares do controlador de navegação. Estes incluem o botão Voltar (& lt; iCloud), um botão de opções (Editar) e a descrição na barra de título (a pasta atual, Core iOS). Cada elemento é criado usando a API do controlador de navegação para apresentar uma hierarquia de contas de e-mail e caixas de correio.
A diferença está na parte inferior da árvore de navegação, ao nível das mensagens individuais que formam as folhas da estrutura de dados. O padrão iPhone-família usa chevrons para indicar folhas. Quando selecionados, esses controladores de exibição de folhas são empurrados para a pilha de navegação. Eles se juntam aos outros controladores da view que rastreiam o progresso de um usuário através da interface. O iPad não envolve suas folhas. Ele os apresenta em uma visão separada e omite chevrons que, de outra forma, indicam que os usuários alcançaram a extensão da passagem hierárquica.
Os controladores de navegação estilo iPhone também desempenham papéis no iPad. Quando os aplicativos iPad usam controladores de navegação padrão (estilo do iPhone), eles geralmente o fazem em contextos estreitos, como apresentações de popover transientes, onde o controlador é apresentado na tela em uma visão pequena com vida útil limitada. Caso contrário, os aplicativos iPad são incentivados a usar a abordagem de vista dividida que ocupa toda a tela.
Usando controladores de navegação e pilhas.
Todo controlador de navegação possui um controlador de visualização de raiz. Este controlador forma a base de sua pilha. Você pode empurrar programmaticamente outros controladores para a pilha, pois o usuário faz escolhas ao navegar pela árvore do modelo e rsquo; s. Embora a própria árvore possa ser multidimensional, o caminho do usuário (essencialmente sua história) é sempre uma linha direta que representa as escolhas já feitas até à data. A mudança para uma nova escolha amplia a trilha de navegação do navegador e cria automaticamente um botão Voltar cada vez que um novo controlador de visualização é empurrado para a pilha.
Os usuários podem tocar um botão Voltar para os controladores pop fora da pilha. O nome de cada botão é o título do controlador de exibição mais recente. À medida que você retorna através da pilha de controladores de exibição anteriores, cada botão Voltar indica o controlador de exibição que pode ser retornado. Os usuários podem voltar a aparecer até chegarem à raiz. Então eles não podem ir mais longe. A raiz é a base da árvore, e você não pode ir além dessa raiz.
Este design baseado em pilha permanece mesmo quando você planeja usar apenas um controlador de exibição. Você pode querer aproveitar a barra de navegação incorporada UINavigationController & rsquo; s para criar um utilitário simples que usa um menu de dois botões, por exemplo. Isso ignoraria qualquer vantagem de navegação da pilha. Você ainda precisa definir esse controlador como a raiz via initWithRootViewController :.
Controles de exibição de Pushing and Popping.
Adicione novos itens na pilha de navegação, pressionando um novo controlador com pushViewController: animado :. Cada controlador de visualização fornece uma propriedade navigationController. Esta propriedade aponta para o controlador de navegação no qual esse controlador está participando. A propriedade isnil se o controlador não for empurrado para uma pilha de navegação.
Use a propriedade navigationController para empurrar um novo controlador de visualização para a pilha de navegação e chame o método de envio no controlador de navegação. Quando pressionado, o novo controlador desliza na tela da direita (assumindo que você define animado para SIM). Aparece um botão Voltar apontando para trás, levando você um passo atrás na pilha. O botão Voltar usa um chevron juntamente com o título do controlador de exibição anterior na pilha de navegação. Substitua o chevron por uma imagem personalizada, definindo a propriedade backIndicatorImage. Tenha sempre cuidado ao substituir os elementos padrão da Apple. Certifique-se de manter o espírito das Diretrizes de Interface Humana da Apple (HIG).
Você pode empurrar uma nova visão por vários motivos. Normalmente, isso envolve a navegação para exibições especiais, como visualizações de detalhes ou perfuração de uma estrutura de arquivos ou hierarquia de preferências. Você pode empurrar controladores para a pilha do controlador de navegação depois que seu usuário toque um botão, um item de tabela ou um acessório de divulgação.
Há pouca razão para sub-classificar UINavigationController. Execute solicitações de envio e personalização da barra de navegação (como configurar o título ou os botões de uma barra) dentro das subclasses UIViewController. A personalização é passada para o controlador de navegação dos controladores filho.
Na maior parte, você não consegue acessar o controlador de navegação diretamente. As exceções a esta regra incluem gerenciar os botões da barra de navegação, alterar a aparência da barra e rsquo; s inicializar com uma classe de barra de navegação personalizada. Você pode alterar um estilo de barra ou sua cor de matiz acessando a propriedade thenavigationBar diretamente, da seguinte maneira:
Esteja ciente de que no iOS 7, a Apple adicionou barTintColor para matizar o fundo da barra em vez de tintColor. A propriedade tintColor é reutilizada para itens de botões da barra de matiz.
Para adicionar novos botões, você modifica seu navigationItem, que fornece uma classe de representação que descreve o conteúdo mostrado na barra de navegação, incluindo os itens do botão da barra esquerda e direita e sua exibição de título. Aqui, é como você pode atribuir um botão à barra:
self. navigationItem. rightBarButtonItem = [[UIBarButtonItem alloc]
initWithTitle: @ Estilo "Ação": UIBarButtonItemStylePlain target: self.
Para remover um botão, atribua o item a zero. Os itens do botão barra não são visualizações. São classes que contêm títulos, estilos e informações de retorno de chamada que itens de navegação e barras de ferramentas usam para criar botões reais nas interfaces. O iOS não fornece acesso às visualizações dos botões criadas pelos itens do botão da barra e seus itens de navegação.
Começando no iOS 5, você pode adicionar vários itens de botão de barra para a esquerda e para a direita. Atribua uma matriz às propriedades rightBarButtonItems (observe as propriedades s) ou leftBarButtonItems para o item de navegação:
O foco de design do iOS 7 é o conteúdo e o conteúdo da sua aplicação, mais especificamente, o conteúdo do seu usuário. Bordas e sombras foram removidas e a transparência foi adicionada nas barras de navegação e outros elementos de UI. Esta alteração afeta significativamente o layout de suas visualizações, especialmente quando você está usando uma barra de navegação.
Começando com o iOS 7, todos os controladores de exibição usam layout em tela cheia. A propriedade wantFullScreenLayout no UIViewController foi obsoleta, e configurá-lo para NO provavelmente levará a um layout muito inesperado. Com o layout de tela cheia, o controlador de visualização dimensionará sua exibição para preencher toda a tela, passando completamente sob a barra de status do sistema translúcido. Além disso, por padrão, todas as barras no iOS 7 agora são translúcidas para revelar ainda mais o conteúdo subjacente.
O fluxo de conteúdo sob barras mudará seu conteúdo de maneiras estranhas em versões anteriores. Você deve incluir ativamente a área debaixo da barra de status e suas próprias barras em seu layout.
Para fornecer mais controle sobre a colocação, o UIViewController agora fornece uma série de novas propriedades de layout. Gerencie a visibilidade da barra de status no nível do controlador de visualização executando prefersStatusBarHidden em suas subclasses e retornando um Booleano apropriado. Muitas das novas propriedades permitem o posicionamento ou dimensionamento de visualizações com base nas barras atualmente exibidas.
Para os controladores de visualização, agora você pode especificar quais bordas da vista devem ser estendidas em barras translúcidas, definindo edgesForExtendedLayout. Por padrão, esta propriedade é UIRectEdgeAll & mdash, o que significa que todas as suas arestas se estenderão através dos elementos translúcidos, como mostrado na Figura 7-2 (esquerda). Você também pode especificar qualquer (s) borda (s) específica (s) ou UIRectEdgeNone, interrompendo a borda da exibição de conteúdo quando chegar à barra, como mostrado na Figura 7-2 (direita). Por padrão, edgeForExtendedLayout também inclui barras opacas. SetextendedLayoutIncludesOpaqueBars para NO para alterar este comportamento.
Figura 7-2 No iOS 7, edgeForExtendedLayout no UIViewController controla a borda da vista usada para layout. UIRectEdgeAll, o padrão, estende a borda através das barras translúcidas (esquerda). UIRectEdgeNone pára a borda na extensão das barras (direita).
As visualizações de rolagem também são afetadas pela barra de status do sistema e barras implementadas pelo desenvolvedor (barra de navegação, barra de ferramentas e barra de abas). Por padrão, UIScrollViews ajusta automaticamente suas inserções de conteúdo para lidar com esses elementos de barra. Para desativar esse comportamento e gerenciar manualmente as inserções de exibição de rolagem, defina automaticamenteAdjustsScrollViewInsets como NO.
Finalmente, para auxiliar na apresentação de conteúdo dentro de seus pontos de vista, o iOS 7 fornece as propriedades topLayoutGuide e bottomLayoutGuide. Essas propriedades indicam as bordas da barra superior e inferior na visualização do seu controlador de visualização. A localização representada depende das barras visíveis.
Barra de status, mas nenhuma barra de navegação está visível & mdash; parte inferior da barra de status.
Barra de navegação visível e mdash; parte inferior da barra de navegação.
Nenhum status ou barra de navegação visível & mdash; topo da tela.
Barra de ferramentas ou barra de abas visível & mdash; topo da barra de ferramentas ou barra de abas.
Nenhuma barra de ferramentas ou barra de abas é visível & mdash; na parte inferior da tela.
Use essas propriedades para criar restrições relativas, posicionando suas subpastações em relação às bordas da barra, independentemente da localização do quadro ou conhecimento prévio da visibilidade da barra. Use-os com restrições de Layout Automático tanto no Interface Builder (IB) quanto no seu código de layout. Fora do layout automático, use guias no posicionamento baseado em quadro. Referenciar o valor do deslocamento na propriedade do comprimento do guia & rsquo; s.
Receita: A Classe de Item de Navegação.
Os objetos que preenchem a barra de navegação são postos em prática usando a classe UINavigationItem, que é uma classe que armazena informações sobre esses objetos. As propriedades do item de navegação incluem os itens do botão da barra esquerda e direita, o título mostrado na barra, a exibição usada para mostrar o título e qualquer botão Voltar usado para navegar de volta da visualização atual.
Esta classe permite anexar botões, texto e outros objetos UI em três locais principais: a esquerda, o centro e a direita da barra de navegação. Normalmente, isso funciona para ser um botão regular à direita, algum texto (geralmente o título UIViewController & rsquo; s) no meio, e um botão Back-style à esquerda. Mas você não está limitado a este layout. Você pode adicionar controles personalizados a qualquer um dos três locais: a esquerda, o centro (área do título) e a direita. Você pode criar barras de navegação com campos de pesquisa no meio em vez disso, ou controles de segmento, barras de ferramentas, imagens e muito mais. Além disso, você pode adicionar vários itens às matrizes dos botões direito e esquerdo. Tudo isso é fácil de modificar.
A área do título central é especialmente personalizável. Você pode atribuir um título ao item de navegação como este:
self. navigationItem. title = @ "Meu título"
Isso equivale a definir a propriedade do título do controlador de exibição e rsquo; diretamente. A maneira mais simples de personalizar o título real é usar a propriedade do título do controlador de exibição filho em vez do item de navegação:
Quando atribuído, o controlador de navegação usa o título para estabelecer o botão Voltar & rsquo; s & ldquo; go back & rdquo; texto. Se você pressionar um novo controlador em cima de um controlador intitulado "Olá", o botão Voltar indica que ele liga para "Olá".
Você também pode substituir o título baseado em texto por uma exibição personalizada, como um controle. Este código adiciona um controle segmentado personalizado, mas isso pode ser uma visão de imagem, um stepper ou qualquer outra coisa:
[[UISegmentedControl alloc] initWithItems: items];
As macros simplificam seu trabalho ao criar botões de barra porque a tarefa de criação é tão repetitiva. A seguinte macro cria um item de botão básico:
#define BARBUTTON (TITLE, SELECTOR) [[UIBarButtonItem alloc] \
Você fornece um título e um seletor para ligar. Cada chamada para esta macro especifica apenas o título e o seletor, apertando a legibilidade do código & rsquo; s:
Esta versão da macro assume que o alvo é "auto", o que é bastante comum, embora você possa facilmente adaptar isso. A macro a seguir adiciona um alvo que você especifica:
#define BARBUTTON_TARGET (TITLE, TARGET, SELECTOR) \
[[UIBarButtonItem alloc] initWithTitle: TITLE \
estilo: UIBarButtonItemStylePlain target: ação TARGET: SELECTOR]
O vocabulário dos botões de barras que você usa varia de acordo com suas demandas específicas de aplicativos. É fácil criar macros para itens do sistema fornecidos pela Apple, itens de imagem criados a partir de recursos de imagem e itens de visualização personalizados, que podem incorporar controles e outros elementos de botão sem barra.
A Receita 7-1 combina esses recursos para demonstrar como os títulos do controlador e os itens de navegação se acumulam durante a perfuração. Ele oferece uma interface super-simples: você seleciona o título para o próximo item que deseja empurrar para a pilha de navegação, e então você empurra-o. Isso permite que você veja como a pilha do controlador de navegação cresce usando o comportamento padrão.
Receita 7-1 Perfuração de Navegação Básica.
// Array of strings.
retornar componentes [@ "Foo * Bar * Baz * Qux "SeparatedByString: @" * "];
[[TestBedViewController alloc] init];
self. view = [[UIView alloc] init];
self. view. backgroundColor = [UIColor whiteColor];
seg = [[UISegmentedControl alloc] initWithItems:
[auto labelWithTitle: @ "Selecionar Título para Pushed Controller"];
CONSTRAIN (self. view, label, @ "H: | - [label (& gt; = 0)] - |");
NSDictionaryOfVariableBindings (seg, label, topLayoutGuide));
Para encontrar o projeto de amostra completa dessa receita, aponte seu navegador para https: // github / erica / iOS-7-Cookbook e vá para a pasta para o Capítulo 7.
Receita: apresentação modal.
Com os controladores de navegação normais, você empurra o seu caminho ao longo das visualizações, parando ocasionalmente para voltar às visualizações anteriores. Essa abordagem pressupõe que você está perfurando seu caminho para cima e para baixo um conjunto de dados que corresponde à estrutura de exibição baseada em árvore que você está usando. A apresentação modal oferece outra maneira de mostrar um controlador de visualização.
Depois de enviar o presenteViewController: animado: conclusão: mensagem para um controlador de exibição, o controlador de exibição especificado aparece na tela e assume o controle até que ele seja demitido com dismissViewControllerAnimated: conclusão :. Isso permite que você adicione diálogos de propósito especial aos seus aplicativos que vão além das visualizações de alerta.
Normalmente, os controladores modais levam os usuários a escolher dados, como contatos de Contatos ou fotos de Fotos ou executar uma tarefa de curta duração, como enviar e-mail ou preferências de configuração. Use controladores modais em qualquer configuração onde faça sentido executar uma tarefa de tempo limitado que se encontra fora do escopo normal do controlador de exibição ativo.
As apresentações modal podem usar quatro estilos de transição:
Slide & mdash; Este estilo de transição desliza uma nova visão sobre o antigo.
Flip & mdash; Este estilo de transição passa uma visão para o & ldquo; back & rdquo; da apresentação.
Fade & mdash; Esse estilo de transição dissolve a nova visão em visibilidade.
Curl & mdash; este estilo de transição faz com que a visão primária se enrolle para fora do caminho para revelar a nova visão abaixo dela.
Defina esses estilos na propriedade modalTransitionStyle do controlador de exibição apresentado. O padrão, UIModalTransitionStyleCoverVertical, desliza a vista modal para cima e sobre o controlador de exibição atual. Quando demitido, desliza de volta.
UIModalTransitionStyleFlipHorizontal executa um flip de frente para a frente da direita para a esquerda. Parece que você está revelando o verso da visão atualmente apresentada. Quando demitido, ele volta para trás, da esquerda para a direita.
UIModalTransitionStyleCrossDissolve desaparece a nova visualização em relação à anterior. Ao demitir-se, ele volta à visão original.
Use UIModalTransitionStylePartialCurl para enrolar o conteúdo (da forma como o aplicativo Maps faz) para revelar uma visualização de configurações modais & ldquo; embaixo do & rdquo; o controlador de visualização principal.
No iPhone e no iPod touch, os controladores modais sempre ocupam completamente a tela. O iPad oferece apresentações mais matizadas. O iPad oferece cinco estilos de apresentação definidos pela propriedade modalPresentationStyle:
Full screen & mdash; uma apresentação em tela cheia (UIModalPresentationFullScreen) é padrão no iPhone, onde a nova vista modal cobre completamente a tela e qualquer conteúdo existente. Este é o único estilo de apresentação legal para cachos; qualquer outro estilo de apresentação eleva uma exceção de tempo de execução, bloqueando o aplicativo.
Folha de página & mdash; no estilo da folha de página (UIModalPresentationPageSheet), a cobertura é padrão para uma relação de aspecto de retrato, de modo que o controlador de visão modal cobre completamente a tela no modo retrato e cobre parcialmente a tela no modo paisagem, como se um pedaço de retrato alinhado O papel foi adicionado ao visor.
Folha de formulário & mdash; o visor de folha de formulário (UIModalPresentationFormSheet) abrange uma pequena parte central da tela, permitindo que você mude o foco para o elemento modal, mantendo a visibilidade máxima da visualização principal do aplicativo.
Current context & mdash; Este é o estilo de apresentação do controlador de visualização pai do view & rsquo; s (UIModalPresentationCurrentContext).
Custom & mdash; Esse estilo de apresentação personalizado (UIModalPresentationCustom), gerenciado pela API de transições personalizadas, foi adicionado no iOS 7.
Esses estilos são melhor experimentados no modo paisagem para diferenciar visualmente a apresentação da folha de página da tela cheia.
O iOS 7 apresenta um modelo para criar transições personalizadas entre controladores de exibição para aumentar os fornecidos pelo sistema. Custom transitions provide nearly unlimited flexibility in creating creative transitions that can be used nearly anywhere that view controllers currently transition, including modal presentation and navigation controller stack changes.
Presenting a Custom Modal Information View.
Presenting a modal controller branches off from your primary navigation path, introducing a new interface that takes charge until your user explicitly dismisses it. You present a modal controller like this:
[self presentViewController:someControllerInstance animated:YES completion:nil];
The controller that is presented can be any kind of view controller subclass, as well. In the case of a navigation controller, the modal presentation can have its own navigation hierarchy built as a chain of interactions. Use the completion block to finish up any tasks you need to perform after the view controller has animated into place.
Always provide a Done option of some kind to allow users to dismiss the controller. The easiest way to accomplish this is to present a navigation controller and add a bar button to its navigation items with an action:
[self dismissViewControllerAnimated:YES completion:nil];
Storyboards simplify the creation of modal controller elements. Drag in a navigation controller instance, along with its paired view controller, and add a Done button to the provided navigation bar. Set the view controller’s class to your custom modal type and connect the Done button to thedone: method. Name your navigation controller in the Attributes inspector so that you can use that identifier to load it.
You can either add the modal components to your primary storyboard or create them in a separate file. Recipe 7-2 loads a custom file (Modal.
DeviceType. storyboard), but you can just as easily add the elements in your MainStoryboard_ DeviceType file.
Recipe 7-2 provides the key pieces for creating modal elements. The presentation is performed in the application’s main view controller hierarchy. Here, users select the transition and presentation styles from segmented controls, but these are normally chosen in advance by the developer and set in code or in IB. This recipe offers a toolbox that you can test on each platform, using each orientation to explore how each option looks.
As of the initial iOS 7 release, a well-reported issue exists in the full-screen flip transition presented in Recipe 7-2 . The navigation bar contents drop abruptly into position at the end of the animation. Hopefully, this issue will be resolved in a future iOS release.
Recipe 7-2 Presenting and Dismissing a Modal Controller.
// Presenting the controller.
// Load info controller from storyboard.
UIStoryboard *storyBoard = [UIStoryboard.
// Partial curl with any non-full-screen presentation.
// raises an exception.
self. view = [[UIView alloc] init];
self. view. backgroundColor = [UIColor whiteColor];
[[UISegmentedControl alloc] initWithItems:
[@"Slide Fade Flip Curl"
[NSArray arrayWithObjects:@"Full Screen",
@"Page Sheet", @"Form Sheet", nil];
[[UISegmentedControl alloc] initWithItems:
id topLayoutGuide = self. topLayoutGuide;
To find this recipe’s full sample project, point your browser to https://github/erica/iOS-7-Cookbook and go to the folder for Chapter 7.
Recipe: Building Split View Controllers.
Using split view controllers is the preferred way to present hierarchically driven navigation on the iPad. Such a controller generally consists of a table of contents on the left and a detail view on the right, although the class (and Apple’s guidelines) is not limited to this presentation style. The heart of the class consists of the notion of an organizing section (master) and a presentation section (detail), both of which can appear onscreen simultaneously in landscape orientation, and whose organizing section optionally converts to a popover in portrait orientation. (You can override this default behavior by implementing splitViewController:shouldHideViewController:inOrientation: in your delegate, letting your split view show both sections in portrait mode.)
Figure 7-3 shows the very basic split view controller built by Recipe 7-3 in landscape (left) and portrait (right) orientations. This controller sets the color of the detail view by selecting an item from the list in the root view. In landscape, both views are shown at once. In portrait orientation, the user must tap the upper-left button on the detail view to access the root view as a popover or use an optional swipe gesture. When programming for this orientation, be aware that the popover can interfere with detail view, as it is presented over that view; design accordingly.
Figure 7-3 At their simplest, split view controllers consist of an organizing pane and a detail view pane. The organizing pane, which you see in this figure, is normally hidden in portrait orientation (right). Users view it via a popover accessed from a navigation bar button or invoke it with a swipe gesture.
The code in Recipe 7-3 builds three separate objects: the master and detail view controllers and the split view controller that owns the first two. The split view controller always contains two children, the master at index 0 and the detail at index 1.
You’ll want to add the master and detail controllers to navigation controller shells, to provide a consistent interface. In the case of the detail controller, this provides a home for the bar button in portrait orientation. The following method builds the two child view controllers, embeds them into navigation controllers, adds them to a view controller array, and returns a new split view controller that hosts those views:
// Create the navigation-embedded root (master) view.
[[ColorTableViewController alloc] init];
rootVC. title = @"Colors"; // make sure to set the title.
[[UISplitViewController alloc] init];
svc. viewControllers = @[rootNav, detailNav];
The master view controller is often some kind of table view controller, as is the one in Recipe 7-3 . What you see here is pretty much as bare bones as tables get. It is a list of color items (specifically, UIColor method names), each one with a cell title that is tinted to match that color.
When an item is selected, the controller uses its built-in splitViewController property to send a request to its detail view. This property returns the split view controller that owns the root view. From there, the controller can retrieve the split view’s delegate, which has been assigned to the detail view. By casting that delegate to the detail view controller’s class, the root view can affect the detail view more meaningfully. In this extremely simple example, the selected cell’s text tint is applied to the detail view’s background color.
Make sure you set the root view controller’s title property. It is used to set the text for the button that appears in the detail view in portrait mode.
Recipe 7-3 ’s DetailViewController class is about as skeletal an implementation as you can get. It provides the most basic functionality you need to provide a detail view implementation with split view controllers. This consists of the will-hide/will-show method pair that adds and hides that all-important bar button for the detail view.
When the split view controller converts the master view controller into a popover controller in portrait orientation, it passes that new controller to the detail view controller. It is the detail controller’s job to retain and handle that popover until the interface returns to landscape orientation. In this skeletal class definition, a strong property holds onto the popover for the duration of portrait interaction.
Recipe 7-3 Building Detail and Master Views for a Split View Controller.
@interface DetailViewController : UIViewController.
@property (nonatomic, strong)
[[DetailViewController alloc] init];
controller. view. backgroundColor = [UIColor blackColor];
// When omitted, you get the default behavior.
@interface ColorTableViewController : UITableViewController.
[[ColorTableViewController alloc] init];
return @[@"blackColor", @"redColor", @"greenColor", @"blueColor",
@"cyanColor", @"yellowColor", @"magentaColor", @"orangeColor",
return [self selectors].count;
if (!cell) cell = [[UITableViewCell alloc]
NSString *item = [self selectors][indexPath. row];
// On selection, update the main view background color.
UIViewController *controller = [nav topViewController];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
To find this recipe’s full sample project, point your browser to https://github/erica/iOS-7-Cookbook and go to the folder for Chapter 7.
Recipe: Creating Universal Split View/Navigation Apps.
Recipe 7-4 modifies Recipe 7-3 ’s split view controller to provide a functionally equivalent application that runs properly on both iPhone and iPad platforms. Accomplishing this takes several steps that add to Recipe 7-3 ’s code base. You do not have to remove functionality from the split view controller approach, but you must provide alternatives in several places.
Recipe 7-4 uses a macro to determine whether the code is being run on an iPad - or iPhone-style device. It leverages the UIKit user interface idiom as follows:
#define IS_IPAD (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
This macro returns YES when the device characteristics are iPad-like rather than iPhone-like (such as on the iPhone or iPod touch). First introduced in iOS 3.2, which introduced the iPad as a new hardware platform, idioms allow you to perform runtime checks in your code to provide interface choices that fit with the deployed platform.
In an iPhone deployment, the detail view controller code remains identical to Recipe 7-3 , but to be displayed, it must be pushed onto the navigation stack rather than shown side by side in a split view. The navigation controller is set up as the primary view for the application window rather than the split view. A simple check at application launch lets your code choose which approach to use:
[[ColorTableViewController alloc] init];
UINavigationController *nav = [[UINavigationController alloc]
window = [[UIWindow alloc] initWithFrame:
[[UIScreen mainScreen] bounds]];
rootVC = [self splitViewController];
rootVC = [self navWithColorTableViewController];
The rest of the story lies in the two methods of Recipe 7-4 , within the color-picking table view controller. Two key checks decide whether to show disclosure accessories and how to respond to table taps:
On the iPad, disclosure indicators should never be used at the last level of detail presentation. On the iPhone, they indicate that a new view will be pushed on selection. Checking for deployment platform lets your code choose whether to include these accessories in cells.
When you’re working with the iPhone, there’s no option for using split views, so your code must push a new detail view onto the navigation controller stack. Compare this to the iPad code, which only needs to reach out to an existing detail view and update its background color.
In real-world deployment, these two checks would likely expand in complexity beyond the details shown in this simple recipe. You’d want to add a check to your model to determine whether you are, indeed, at the lowest level of the tree hierarchy before suppressing disclosure accessories. Similarly, you might need to update or replace presentations in your detail view controller.
Recipe 7-4 Adding Universal Support for Split View Alternatives.
- (UITableViewCell *)tableView:(UITableView *)tableView.
if (!cell) cell = [[UITableViewCell alloc]
UIViewController *controller = [nav topViewController];
To find this recipe’s full sample project, point your browser to https://github/erica/iOS-7-Cookbook and go to the folder for Chapter 7.
On the iPhone and iPod touch, the UITabBarController class allows users to move between multiple view controllers and to customize the bar at the bottom of the screen. This is best seen in the music application. It offers one-tap access to different views and a More button that leads to user selection and editing of the bottom bar. Tab bars are not recommended for use as a primary design pattern on the iPad, although Apple supports their use when needed, especially in split views and popovers.
With tab bars, you don’t push views the way you do with navigation bars. Instead, you assemble a collection of controllers (they can individually be UIViewControllers, UINavigationControllers, or any other kind of view controllers) and add them to a tab bar by setting the bar’s viewControllers property. Cocoa Touch does the rest of the work for you. Set allowsCustomizing to YES to enable end-user reordering of the bar.
Recipe 7-5 creates 11 simple view controllers of the BrightnessController class. This class sets the background to a specified gray level—in this case, from 0% to 100%, in steps of 10%. Figure 7-4 (left) shows the interface in its default mode, with the first four items and a More button displayed.
Figure 7-4 Tab bar controllers allow users to pick view controllers from a bar at the bottom of the screen (left) and customize the bar from a list of available view controllers (right).
Users may reorder tabs by selecting the More option and then tapping Edit. This opens the configuration panel shown in Figure 7-4 (right). These 11 view controllers offer options a user can navigate through and select from. Note that the navigation bar in Figure 7-4 (right) has not been converted to the standard flat UI appearance as of the iOS 7 release.
Note that the translucent navigation bar background tint is black throughout the entire interface. Apple provides the UIAppearance protocol, which allows you to customize UI properties for all instances of a given class. Recipe 7-5 uses this functionality to tint its navigation bar’s background black:
[[UINavigationBar appearance] setBarTintColor:[UIColor blackColor]];
Starting with iOS 7, tintColor no longer tints the background of bars, such as the navigation bar. To tint the background, use the barTintColor property.
This recipe adds its 11 controllers twice. The first time it assigns them to the list of view controllers available to the user:
The second time it specifies that the user can select from the entire list when interactively customizing the bottom tab bar:
The second line is optional; the first is mandatory. After setting up the view controllers, you can add all or some to the customizable list. If you don’t, you still can see the extra view controllers by tapping the More button, but users won’t be able to include them in the main tab bar on demand.
Tab art appears inverted in color on the More screen. According to Apple, this is the expected and proper behavior. Apple has no plans to change this. It does provide an interesting view contrast when your 100% black swatch appears as pure white on that screen. In addition, in iOS 7, the icon and text for items are now tinted with the inherited tintColor for the application.
Recipe 7-5 Creating a Tab Bar View Controller.
#pragma mark - BrightnessController.
@interface BrightnessController : UIViewController.
// and UIKit image calls.
CGRect rect = CGRectMake(0.0f, 0.0f, 30.0f, 30.0f);
UIBezierPath *path = [UIBezierPath.
colorWithAlphaComponent:(float) aBrightness / 10.0f] set];
// and a tab bar item icon.
self = [super init];
self. title = [NSString stringWithFormat:@"%d%%",
[[UITabBarItem alloc] initWithTitle:self. title.
image:[self buildSwatch:brightness] tag:0];
self. view = [[UIView alloc] init];
[UIColor colorWithWhite:(brightness / 10.0f) alpha:1.0f];
@interface TestBedAppDelegate : NSObject.
@property (nonatomic, strong) UIWindow *window;
// Globally use a black tint for nav bars.
NSMutableArray *controllers = [NSMutableArray array];
for (int i = 0; i <= 10; i++)
tabBarController. tabBar. barTintColor = [UIColor blackColor];
initWithFrame:[[UIScreen mainScreen] bounds]];
To find this recipe’s full sample project, point your browser to https://github/erica/iOS-7-Cookbook and go to the folder for Chapter 7.
On iOS, persistence is golden. When starting or resuming your application from termination or interruption, always return users to a state that closely matches where they left off. This lets your users continue whatever tasks they were involved with and provides a user interface that matches the previous session. Listing 7-1 introduces an example of doing exactly that.
This update to Recipe 7-5 stores both the current tab order and the currently selected tab, and it does so whenever those items are updated. When a user launches the application, the code searches for previous settings and applies them if they are found.
To respond to updates, a tab bar delegate must declare the UITabBarControllerDelegate protocol. The approach used here depends on two delegate methods. The first, tabBarController:didEndCustomizingViewControllers:changed:, provides the current array of view controllers after the user has customized them with the More > Edit screen. This code captures their titles (10%, 20%, and so on) and uses that information to relate a name to each view controller.
The second delegate method is tabBarController:didSelectViewController:. The tab bar controller calls this method each time a user selects a new tab. By capturing the selectedIndex, this code stores the controller number relative to the current array.
In this example, these values are stored using iOS’s built-in user defaults system, NSUserDefaults. This preferences system works very much like a large mutable dictionary. Set values for keys by using setObject:forKey:, as shown here:
[[NSUserDefaults standardUserDefaults] setObject:titles.
Then retrieve them with objectForKey:, like so:
NSArray *titles = [[NSUserDefaults standardUserDefaults]
Synchronizing your settings ensures that the stored defaults dictionary matches your changes:
[[NSUserDefaults standardUserDefaults] synchronize];
When the application launches, it checks for previous settings describing the last selected tab order and selected tab. If it finds them, it uses these settings to set up the tabs and select a tab to make active. Because the titles contain the information about what brightness value to show, this code converts the stored title from text to a number and divides that number by 10 to send to the initialization method.
Most applications aren’t based on such a simple numeric system. If you use titles to store your tab bar order, make sure you name your view controllers meaningfully and in a way that lets you match a view controller with the tab ordering.
You could also store an array of the view tags as NSNumbers or, better yet, use the NSKeyedArchiver class. Archiving lets you rebuild views using state information that you store on termination. Another option is the state preservation system introduced in iOS 6.
Listing 7-1 Storing Tab State to User Defaults.
// Collect and store the view controller order.
NSMutableArray *titles = [NSMutableArray array];
for (UIViewController *vc in viewControllers)
[[NSUserDefaults standardUserDefaults] synchronize];
// Store the selected tab.
[NSNumber numberWithInt:[controller selectedIndex]];
[[NSUserDefaults standardUserDefaults] synchronize];
// Globally use a black tint for nav bars.
NSArray *titles = [[NSUserDefaults standardUserDefaults]
// titles retrieved from user defaults.
for (NSString *theTitle in titles)
([theTitle intValue] / 10)];
// generate all new controllers.
for (int i = 0; i <= 10; i++)
tabBarController. tabBar. barTintColor = [UIColor blackColor];
NSNumber *tabNumber = [[NSUserDefaults standardUserDefaults]
tabBarController. selectedIndex = [tabNumber intValue];
initWithFrame:[[UIScreen mainScreen] bounds]];
Recipe: Page View Controllers.
The UIPageViewController class builds a book-like interface that uses individual view controllers as its pages. Users swipe from one page to the next or tap the edges to move to the next page or previous page. You can create a book-looking layout with pages, as shown in Figure 7-5 (left), or use a flat scrolling presentation, as shown in Figure 7-5 (right). The scrolling presentation offers an optional page indicator presentation, which is shown here at the bottom of the view.
Figure 7-5 The UIPageViewController class creates virtual “books” from individual view controllers. View your books in paged (left) or scrolling (right) presentations.
All of a controller’s pages can be laid out in a similar fashion, as in Figure 7-5 , or each page can provide a unique user interaction experience. Apple precooked all the animation and gesture handling into the class for you. You provide the content, implementing delegate and data source callbacks.
Your code customizes a page view controller’s look and behavior. Key properties specify how many pages display simultaneously, the content used for the reverse side of each page, and more. Here’s a rundown of those Apple-specified properties:
The transitionStyle property controls how one view controller transitions to the next. At this writing, the only transition styles supported by the page view controller are the page curl, as shown in Figure 7-5 (left), UIPageViewControllerTransitionStylePageCurl, and the scrolling presentation, UIPageViewControllerTransitionStyleScroll. This latter style was introduced in iOS 6.
The controller’s doubleSided property determines whether content appears on both sides of a page, as shown in Figure 7-5 (left), or just one side (right). Reserve the double-sided presentation for side-by-side layout when showing two pages simultaneously. If you don’t, you’ll end up making half your pages inaccessible. The controllers on the “back” of the pages will never move into the primary viewing space. The book layout is controlled by the book’s spine.
The spineLocation property can be set at the left or right, top or bottom, or center of the page. The three spine constants are UIPageViewControllerSpineLocationMin, corresponding to top or left, UIPageViewControllerSpineLocationMax for the right or bottom, and UIPageViewControllerSpineLocationMid for the center. The first two of these produce single-page presentations; the last, with its middle spine, is used for two-page layouts. Return one of these choices from thepageViewController:spineLocationForInterfaceOrientation: delegate method, which is called whenever the device reorients, to let the controller update its views to match the current device orientation.
Set the navigationOrientation property to specify whether the spine goes left/right or top/bottom. Use either UIPageViewControllerNavigationOrientationHorizontal (left/right) or UIPageViewControllerNavigationOrientationVertical(top/bottom). For a vertical book, the pages flip up and down rather than employing the left and right flips normally used.
Wrapping the Implementation.
Like table views, a page view controller uses a delegate and data source to set the behavior and contents of its presentation. Unlike with table views, it’s simplest to wrap these items into a custom class to hide their details from applications. The code needed to support a page view implementation is rather quirky—but highly reusable. A wrapper lets you turn your attention away from fussy coding details to specific content-handling concerns.
In the standard implementation, the data source is responsible for providing page controllers on demand. It returns the next and previous view controllers in relationship to a given one. The delegate handles reorientation events and animation callbacks, setting the page view controller’s controller array, which always consists of either one or two controllers, depending on the view layout. As Recipe 7-6 demonstrates, it’s a bit of a mess to implement, but once built, it’s something you really don’t need to spend much time coming back to.
Recipe 7-6 creates a BookController class. This class numbers each page, hiding the next/previous implementation details and handling all reorientation events. A custom delegate protocol (BookDelegate) becomes responsible for returning a controller for a given page number when sent the viewControllerForPage: message. This simplifies implementation so that the calling app has only to handle a single method, which it can do by building controllers by hand or by pulling them from a storyboard.
To use the class defined in Recipe 7-6 , you establish the controller, declare it as a child view controller, and add its view as a subview. Adding BookController as a child view controller ensures that it receives orientation and memory events. This type of view controller relationship will be discussed in more detail in the next recipe. Finally, the initial page number is set. Here’s what that code might look like:
bookController = [BookController bookWithDelegate:self.
The book controller creation convenience method also takes a second argument: a style. Recipe 7-6 allows developers to build four styles of books: a traditional book, a vertical book, and two scrolling styles:
BookLayoutStyleBook, // side by side in landscape.
BookLayoutStyleFlipBook, // side by side in portrait.
The standard book presents one page in portrait (spine vertical and to the left) and a side-by-side presentation in landscape (spine vertical in the middle). This corresponds to a standard Western-style book, with page movement going left to right.
The “flip”-style book uses a horizontal spine. In landscape mode, the spine is at the top, with one page shown at a time. In portrait, that extends to two pages, with the horizontal spine in the middle, halfway between top and bottom.
The two scroll layouts allow you to scroll horizontally and vertically through individual pages. You cannot use multipage (side-by-side) layout with scrolling.
The tear-down process in viewWillDisappear allows the book controller to retire from its superview:
Recipe 7-6 handles its delegate and data source duties by tagging each view controller’s view with a page number. It uses this number to know exactly which page is presented at any time and to delegate another class, BookDelegate, to produce a view controller by index.
The page controller itself always stores zero, one, or two pages in its view controller array. Zero pages means the controller has not yet been properly set up. One page is used for spine locations on the edge of the screen, two pages for a central spine. If the page count does not exactly match the spine setup, you will encounter a rather nasty runtime crash.
The controllers presented in those pages are produced by the two data source methods, which implement the before and after callbacks. In the page controller’s native implementation, controllers are defined strictly by their relationship to each other, not by an index. This recipe replaces those relationships with a simple number, asking its delegate for the page at a given index.
Here, given the orientation, the useSideBySide: method determines where to place the spine and thus how many controllers show simultaneously. This implementation sets landscape as side by side and portrait as one page. You may want to change this for your applications. For example, you might use only one page on the iPhone, regardless of orientation, to enhance text readability.
Recipe 7-6 allows both user - and application-based page control. Users can swipe and tap to new pages, or the application can send a moveToPage: request. This allows you to add external controls in addition to the page view controller’s gesture recognizers.
The direction that the page turns is set by comparing the new page number against the old. This recipe uses a Western-style page turn, where higher numbers are to the right and pages flip to the left. You may want to adjust this as needed for countries in the Middle East and Asia.
Recipe 7-6 continually stores the current page to system defaults, so it can be recovered when the application is relaunched. It also notifies its delegate when the user has turned to a given page.
Building a Presentation Index.
Page view controllers’ scrolling layouts allow you to add an optional index (utilizing a page control). Any book that uses the scrolling layout style (UIPageViewControllerTransitionStyleScroll) can implement two data source methods. iOS uses them to build the indicator at the bottom of the scrolling book that you saw in Figure 7-5 (right).
As you can see from this snippet, the implementation since its inception is a bit wobbly:
// Slightly borked in iOS 6 & 7.
// return [self currentPage];
return [bookDelegate numberOfPages];
Apple’s documentation states that presentationIndexForPageViewController should return the index of the selected item. Unfortunately, this leads to madness (and crashes). Returning 0 from the presentation index and the number of pages for the presentation count produces the most stable indicator. The page count used here is deferred to the book’s delegate, via an optional method called numberOfPages.
Note that you are not limited to a one-to-one correlation between your index and your page count and current page number. For a large book, you can imagine dividing this number down somewhat, so each page dot corresponds to 5 or 10 pages, showing progress through the book without an exact page correspondence.
Apple enables you to access a page view controller’s gesture recognizers to allow or disallow touch-based page turns based on a touch’s location on a page. Don’t do it. First, this approach is not valid for scroll-based controllers. Second, adding recognizer delegate methods tends to mess up app stability.
Recipe 7-6 Creating a Page View Controller Wrapper.
// Define a custom delegate protocol for this wrapper class.
@protocol BookControllerDelegate <NSObject>
- (NSInteger)numberOfPages; // for scrolling layouts.
@interface BookController : UIPageViewController.
id <BookControllerDelegate> bookDelegate;
@property (nonatomic, assign) NSUInteger pageNumber;
@property (nonatomic) BookLayoutStyle layoutStyle;
// Page controllers are numbered using tags.
NSInteger pageCheck = ((UIViewController *)[self. viewControllers.
// Slightly borked in iOS 6 & 7.
// return [self currentPage];
if (_bookDelegate && [_bookDelegate.
return [_bookDelegate numberOfPages];
// Update if you'd rather use some other decision strategy.
case BookLayoutStyleVerticalScroll: return NO;
case BookLayoutStyleFlipBook: return isLandscape;
default: return isLandscape;
[[NSUserDefaults standardUserDefaults] synchronize];
if (_bookDelegate && [_bookDelegate respondsToSelector:
BOOL sideBySide = [self useSideBySide:orientation];
NSInteger numberOfPagesNeeded = sideBySide ? 2 : 1;
NSInteger currentCount = self. viewControllers. count;
if (sideBySide && (leftPage % 2))
leftPage = floor(leftPage / 2) * 2;
if (currentCount && (currentCount == numberOfPagesNeeded))
if (_pageNumber == requestedPage) return;
if (_pageNumber == leftPage) return;
NSMutableArray *pageControllers = [NSMutableArray array];
SAFE_ADD(pageControllers, [self controllerAtPage:leftPage]);
[self controllerAtPage:leftPage + 1]);
direction:direction animated:YES completion:nil];
// Thanks Dino Lupo.
[self updatePageTo:_pageNumber + 1];
return [self controllerAtPage:(viewController. view. tag + 1)];
[self updatePageTo:_pageNumber - 1];
return [self controllerAtPage:(viewController. view. tag - 1)];
// Always start with left or single page.
NSUInteger indexOfCurrentViewController = 0;
BOOL sideBySide = [self useSideBySide:orientation];
if ((aStyle == BookLayoutStyleFlipBook) ||
if ((aStyle == BookLayoutStyleHorizontalScroll) ||
// and spacing between vc's (scroll).
BookController *bc = [[BookController alloc]
To find this recipe’s full sample project, point your browser to https://github/erica/iOS-7-Cookbook and go to the folder for Chapter 7.
Apple’s split view controller was groundbreaking in that it introduced the notion that more than one controller could live onscreen at a time. Until the split view, the rule was one controller with many views at a time. With the split view, several controllers coexist onscreen, all of them independently responding to orientation and memory events.
Apple exposed this multiple-controller paradigm to developers in the iOS 5 SDK, allowing developers to design a parent controller and add child controllers to it. Events are passed from parent to child as needed. This allows you to build custom containers, outside the Apple-standard set of containers such as tab bar and navigation controllers.
Recipe 7-7 builds a reusable container that can hold either one or two children. When loaded with two child view controllers, it lets you flip from one to the other and back. It has quite a lot of conditionality built in. That’s because it can be used as a standalone view controller, as a child view controller itself, and as a modal view controller. Imagine the following situations.
As with a navigation controller, you can create this flip view controller directly and set it as your primary window’s root view controller. In that case, it has no further relationship with any hierarchy. It merely manages its children. You can also use it as a child of some other container, such as in a tab bar controller presentation, a split view controller, and so forth. When used in that way, it acts as both a parent of its children and as a child of the container that holds it. Finally, you can present the controller directly. The flip view container must behave as a solid citizen in all these situations. The controller therefore has two tasks. First, it must manage its children using standard UIKit calls. Second, it must be aware of how it is participating in the view hierarchy. This recipe adds a navigation bar so a Done button becomes available to end users.
Adding and Removing a Child View Controller.
In the simplest scenario, adding a child to a container controller takes three steps:
1. Call addChildViewController: on the parent and pass the child as the argument (for example, [self addChildViewController:childvc]).
2. Add the child controller’s view as a subview (for example, [self. view addSubview:childvc. view]).
3. Call didMoveToParentViewController: on the child with the parent as its argument (for example, [childvc didMoveToParentViewController:self]).
To remove a child view controller, the steps are almost (but not quite) mirrored:
1. Call willMoveToParentViewController: on the child, passing nil as the argument (for example, [childvc willMoveToParentViewController:nil]).
2. Remove the child controller’s view (for example, [childvc. view removeFromSuperview]).
3. Call removeFromParentViewController on the child (for example, [childvc removeFromParentViewController]).
Transitioning Between View Controllers.
UIKit offers a simple way to animate view features when you move from one child view controller to another. You provide a source view controller, a destination, and a duration for the animated transition. You can specify the kind of transition in the options. Supported transitions include page curls, dissolves, and flips. This method creates a simple curl from one view controller to the next:
You can use the same approach to animate UIView properties without the built-in transitions. For example, this method re-centers and fades out the red controller while fading in the blue. These are all animatable UIView features and are changed in the animations: block:
redController. view. center = CGPointMake(0.0f, 0.0f);
Using transitions and view animations is an either/or scenario. Either set a transition option or change view features in the animations block. Otherwise, they conflict, as you can easily confirm for yourself. Use the completion block to remove the old view and move the new view into place.
Although simple to implement, this kind of transition is not meant for use with Core Animation. If you want to add Core Animation effects to your view-controller-to-view-controller transitions, think about using a custom segue instead. Segues are covered in the following recipe.
As mentioned in Recipe 7-2 , a third option is available for animating transitions between UIViewControllers in iOS 7: The custom transitions API allows you to create advanced animations that can even interact dynamically with the user.
Recipe 7-7 Creating a View Controller Container.
NSLog(@"Error: No root view controller");
// Please call only with two controllers.
if (controllers. count < 2) return;
UIViewController *front = (UIViewController *)controllers[0];
UIViewController *back = (UIViewController *)controllers[1];
UIViewAnimationOptions transition = reversedOrder ?
[self transitionFromViewController: front.
toViewController:back duration:0.5f options:transition.
animations:nil completion:^(BOOL done)
[UIView animateWithDuration:0.3f animations:^()
controllers = @[back, front];
NSLog(@"Error: No root view controller");
UIViewController *back = nil;
if (controllers. count > 1) back = controllers[1];
BOOL isPresented = self. isBeingPresented;
if (navbar || infoButton)
// iPhone navbar height must consider status bar.
CGFloat navbarHeight = IS_IPHONE ? 64.0 : 44.0;
navbar = [[UINavigationBar alloc] init];
[navbar setItems:@[self. navigationItem] animated:NO];
(navbar != nil) ? navbarHeight : 0.0f;
CGRect destFrame = CGRectMake(0.0f, verticalOffset,
if (controllers. count < 2) return; // our work is done here.
infoButton = [UIButton buttonWithType:UIButtonTypeInfoLight];
infoButton. tintColor = [UIColor whiteColor];
[infoButton addTarget:self action:@selector(flip:)
To find this recipe’s full sample project, point your browser to https://github/erica/iOS-7-Cookbook and go to the folder for Chapter 7.
When you use storyboards, IB provides a set of standard segues to transition between your view controllers. With custom containers come their little brother, custom segues. Just as tab and navigation controllers provide a distinct way of transitioning between child view controllers, you can build custom segues that define transition animations unique to your class.
IB doesn’t provide a lot of support for custom containers with custom segues, so it’s best to develop your segue presentations in code for now. Here’s how you might implement code to move a view controller to a new view:
// Informal custom delegate method.
// Retrieve the two vc's.
if (vcIndex == newIndex) return;
Here, the code identifies the source and destination child controllers, builds a segue, sets its parameters, and tells it to perform. An informal delegate method is called back by that custom segue on its completion. Recipe 7-8 shows how the segue is built. In this example, it creates a rotating cube effect that moves from one view to the next. Figure 7-6 shows the segue in action.
Figure 7-6 Custom segues allow you to create visual metaphors for your custom containers. Recipe 7-8 builds a “cube” of view controllers that can be rotated from one to the next. The switches on each controller update the art alpha value from translucent to solid and back.
The segue’s goesForward property determines whether the rotation moves to the right or left around the virtual cube. Although this example uses four view controllers, as you saw in the code that laid out the child view controllers, that’s a limitation of the metaphor, not of the code itself, which will work with any number of child controllers. You can just as easily build three - or seven-sided presentations with this, although you are breaking an implicit “reality” contract with your user if you do so. To add more (or fewer) sides, you should adjust the animation geometry in the segue away from a cube to fit your virtual n - hedron.
Recipe 7-8 Creating a Custom View Controller Segue.
UIView __weak *hostView;
- (UIImage *)screenShot:(UIView *)aView.
// Arbitrarily dims to 40%. Adjust as desired.
- (CALayer *)createLayerFromView:(UIView *)aView.
CALayer *imageLayer = [CALayer layer];
imageLayer. anchorPoint = CGPointMake(1.0f, 1.0f);
UIImage *shot = [self screenShot:aView];
imageLayer. contents = (__bridge id) shot. CGImage;
// remove the animation, and ping the delegate.
CAAnimationGroup *group = [CAAnimationGroup animation];
float multiplier = goesForward ? -1.0f : 1.0f;
CABasicAnimation *translationX = [CABasicAnimation.
[NSNumber numberWithFloat:multiplier * halfWidth];
translationZ. toValue = [NSNumber numberWithFloat:-halfWidth];
[NSNumber numberWithFloat: multiplier * M_PI_2];
group. animations = [NSArray arrayWithObjects:
rotationY, translationX, translationZ, nil];
[transformationLayer addAnimation:group forKey:kAnimationKey];
transformationLayer = [CALayer layer];
transformationLayer. anchorPoint = CGPointMake(0.5f, 0.5f);
CATransform3D sublayerTransform = CATransform3DIdentity;
sublayerTransform. m34 = 1.0 / -1000;
CATransform3D transform = CATransform3DMakeIdentity;
// at a 90/270 degree angle off the main.
transform = CATransform3DRotate(transform, M_PI_2, 0, 1, 0);
hostView. frame. size. width, 0, 0);
CATransform3DRotate(transform, M_PI_2, 0, 1, 0);
hostView. frame. size. width, 0, 0);
CATransform3DRotate(transform, M_PI_2, 0, 1, 0);
hostView. frame. size. width, 0, 0);
To find this recipe’s full sample project, point your browser to https://github/erica/iOS-7-Cookbook and go to the folder for Chapter 7.
Starting in the iOS 6 SDK, you can apply custom segues in your storyboards. You’ll need to tie those segues to some action item, such as a button or bar button press, or similar actionable element. Figure 7-7 shows how custom segues are listed in IB. The “rotating” segue is from Recipe 7-8 .
Figure 7-7 Storyboards allow you to apply custom segues in IB. IB scans for UIStoryboardSegue child classes. Here, IB lists the custom “rotating” segue along with system-supplied options.
What’s more, segues can be “unwound.” Unwinding allows you to move back from a new view controller to its logical parent, using a custom segue you provide. You achieve this by implementing a few methods:
Specify whether you can unwind with canPerformUnwindSegueAction:fromViewController:withSender:.
Return a view controller to viewControllerForUnwindSegueAction:fromViewController:withSender:. This controller will be the unwinding destination.
Supply the required unwinding segue instance via segueForUnwindingToView-Controller:fromViewController:identifier:. Typically, you’ll want your unwind to animate in the reverse direction from your original segue.
Finally, you can now allow or disallow any segue by implementing shouldPerformSegue-WithIdentifier:sender:. You return either YES or NO, depending on whether you want the identified segue to proceed.
This chapter shows many view controller classes in action. You’ve learned how to use them to handle view presentation and user navigation for various device deployment choices. With these classes, you have discovered how to expand virtual interaction space and create multipage interfaces, as demanded by applications, while respecting the HIG on the platform in question. Before moving on to the next chapter, here are a few points to consider about view controllers:
Use navigation trees to build hierarchical interfaces. They work well for looking at file structures or building a settings tree. When you think “disclosure view” or “preferences,” consider pushing a new controller onto a navigation stack or using a split view to present them directly.
Don’t be afraid to use conventional UI elements in unconventional ways, as long as you respect the overall Apple HIG. You can apply innovative approaches for UINavigationController that don’t involve any navigation. The tools are there for you to use.
Seja persistente. Let your users return to the same GUI state that they last left from. NSUserDefaults provides a built-in system for storing information between application runs. Use these defaults to re-create the prior interface state. The State Preservation and Restoration API introduced in iOS 6 provides another path for persisting large portions of your UI state.
Go universal. Let your code adapt itself for various device deployments rather than force your app into an only-iPhone or only-iPad design. This chapter touches on some simple runtime device detection and interface updates that you can easily expand for more challenging circumstances. Universal deployment isn’t just about stretching views and using alternate art and XIB files. It’s also about detecting when a device influences the way you interact in addition to the look of the interface.
When working with custom containers, don’t be afraid of using storyboards directly. You do not have to build and retain an array of all your controllers simultaneously. Storyboards offer direct access to all your elements. As with the new page view controller class, just load the controllers you need, when you need them.

Comments

Popular posts from this blog

Forex é legal em que países

Forex amazon

Forex balikbayan toronto