Para esclarecer o objetivo desta pergunta: Eu sei como criar visualizações complicadas com ambas as subvisões e usando o drawRect. Estou tentando entender completamente o quando e por que usar um sobre o outro.
Também entendo que não faz sentido otimizar isso muito antes do tempo e fazer algo da maneira mais difícil antes de fazer qualquer criação de perfil. Considere que estou confortável com os dois métodos e agora realmente quero um entendimento mais profundo.
Muita confusão vem de aprender como tornar o desempenho de rolagem de exibição de tabela muito suave e rápido. É claro que a fonte original desse método é do autor por trás do twitter para iPhone (anteriormente tweetie). Basicamente, diz que, para tornar a rolagem da mesa mais suave, o segredo é NÃO usar subviews, mas fazer todo o desenho em uma visualização personalizada. Essencialmente, parece que o uso de muitas subvisões diminui a renderização porque elas têm muita sobrecarga e são constantemente recompostas nas visualizações pai.
Para ser justo, isso foi escrito quando o 3GS era bastante novo, e os iDevices ficaram muito mais rápidos desde então. Ainda assim, esse método é sugerido regularmente nas interwebs e em outros lugares para tabelas de alto desempenho. Na verdade, é um método sugerido no Table Sample Code da Apple , foi sugerido em vários vídeos da WWDC ( desenho prático para desenvolvedores de iOS ) e em muitos livros de programação para iOS .
Existem ainda ferramentas incríveis para projetar gráficos e gerar o código de gráficos principais para eles.
Então, no começo, sou levado a acreditar que "existe uma razão pela qual o Core Graphics existe. É RÁPIDO!"
Mas assim que penso que recebo a idéia "Favorecer gráficos principais quando possível", começo a perceber que o drawRect geralmente é responsável pela falta de resposta em um aplicativo, é extremamente caro em termos de memória e realmente sobrecarrega a CPU. Basicamente, eu deveria " Evitar substituir o drawRect " ( Desempenho do aplicativo iOS da WWDC 2012 : gráficos e animações )
Então eu acho que, como tudo, é complicado. Talvez você possa ajudar a mim e a outras pessoas a entender os quando e por que usar o drawRect?
Vejo algumas situações óbvias para usar o Core Graphics:
- Você tem dados dinâmicos (exemplo do gráfico de ações da Apple)
- Você tem um elemento de interface do usuário flexível que não pode ser executado com uma imagem redimensionável simples
- Você está criando um gráfico dinâmico que, uma vez renderizado, é usado em vários locais
Vejo situações para evitar gráficos principais:
- As propriedades da sua visualização precisam ser animadas separadamente
- Você tem uma hierarquia de exibição relativamente pequena, portanto, qualquer esforço extra percebido usando o CG não vale o ganho
- Você deseja atualizar partes da vista sem redesenhar a coisa toda
- O layout de suas subvisões precisa ser atualizado quando o tamanho da visualização principal for alterado
Portanto, conceda seu conhecimento. Em que situações você alcança o drawRect / Core Graphics (que também pode ser realizado com subvisões)? Quais fatores levam você a essa decisão? Como / por que o desenho em uma exibição personalizada é recomendado para rolagem suave de células da tabela, mas a Apple recomenda o drawRect por razões de desempenho em geral? E as imagens de fundo simples (quando você as cria com CG vs usando uma imagem png redimensionável)?
Talvez não seja necessário um entendimento profundo desse assunto para criar aplicativos que valham a pena, mas não gosto de escolher entre técnicas sem poder explicar o porquê. Meu cérebro fica bravo comigo.
Pergunta Update
Obrigado pela informação a todos. Algumas perguntas esclarecedoras aqui:
- Se você está desenhando algo com gráficos principais, mas pode realizar o mesmo com UIImageViews e um png pré-renderizado, sempre deve seguir esse caminho?
- Uma pergunta semelhante: especialmente com ferramentas duras como esta , quando você deve considerar desenhar elementos de interface em gráficos principais? (Provavelmente quando a exibição do seu elemento é variável. Por exemplo, um botão com 20 variações de cores diferentes. Algum outro caso?)
- Dado o meu entendimento na minha resposta abaixo, os ganhos de desempenho de uma célula de tabela poderiam ser obtidos capturando efetivamente um bitmap de instantâneo da sua célula após a renderização do UIView complexo e exibindo-o enquanto rolava e oculta a visualização complexa? Obviamente, algumas peças teriam que ser trabalhadas. Apenas um pensamento interessante que tive.
fonte
Vou tentar manter um resumo do que estou extrapolando das respostas de outras pessoas aqui e fazer perguntas esclarecedoras em uma atualização para a pergunta original. Mas encorajo outras pessoas a manterem as respostas e votarem nos que forneceram boas informações.
Abordagem geral
É bastante claro que a abordagem geral, como Ben Sandofsky mencionou em sua resposta , deve ser "Sempre que puder, use o UIKit. Faça a implementação mais simples que funcionar. Perfil. Quando houver um incentivo, otimize".
O porquê
Desenhar o conteúdo das células em um UIView simples pode melhorar muito o seu FPS nas tabelas de rolagem.
Como eu disse acima, CPU e GPU são dois possíveis gargalos. Como eles geralmente lidam com coisas diferentes, você deve prestar atenção a qual gargalo você está enfrentando. No caso de rolagem de tabelas, não é que o Core Graphics esteja atraindo mais rapidamente, e é por isso que ele pode melhorar bastante o seu FPS.
De fato, os gráficos principais podem muito bem ser mais lentos que uma hierarquia UIView aninhada para a renderização inicial. No entanto, parece que o motivo típico para rolagem irregular é que você está afunilando a GPU, portanto, é necessário resolver isso.
Por que substituir o drawRect (usando gráficos principais) pode ajudar na rolagem da tabela:
Pelo que entendi, a GPU não é responsável pela renderização inicial das exibições, mas recebe texturas ou bitmaps, às vezes com algumas propriedades de camada, depois de renderizadas. Ele é responsável por compor os bitmaps, renderizar todos esses efeitos de camada e a maioria das animações (Core Animation).
No caso de células de exibição de tabela, a GPU pode ter gargalos com hierarquias de exibição complexas, porque, em vez de animar um bitmap, está animando a exibição pai e fazendo cálculos de layout de subvisões, efeitos de camada de renderização e composição de todas as subvisões. Portanto, em vez de animar um bitmap, ele é responsável pelo relacionamento de vários bitmaps e como eles interagem na mesma área de pixels.
Portanto, em resumo, o motivo de desenhar sua célula em uma visualização com gráficos principais pode acelerar a rolagem da tabela NÃO é porque está desenhando mais rápido, mas porque está reduzindo a carga na GPU, que é o gargalo que causa problemas nesse cenário específico .
fonte
Sou desenvolvedor de jogos e fazia as mesmas perguntas quando meu amigo me disse que minha hierarquia de visualizações baseada no UIImageView iria desacelerar meu jogo e torná-lo terrível. Então, comecei a pesquisar tudo o que eu poderia encontrar sobre o uso de UIViews, CoreGraphics, OpenGL ou algo de terceiros como o Cocos2D. A resposta consistente que recebi de amigos, professores e engenheiros da Apple na WWDC foi que não haverá muita diferença no final, porque em algum nível eles estão fazendo a mesma coisa . As opções de nível superior, como UIViews, contam com as opções de nível inferior, como CoreGraphics e OpenGL, apenas envoltas em código para facilitar o uso.
Não use o CoreGraphics se quiser apenas reescrever o UIView. No entanto, você pode ganhar velocidade usando o CoreGraphics, desde que faça todo o desenho em uma vista, mas será que realmente vale a pena ? A resposta que encontrei geralmente não. Quando comecei o jogo, estava trabalhando com o iPhone 3G. À medida que meu jogo crescia em complexidade, comecei a ver algum atraso, mas com os dispositivos mais novos era completamente imperceptível. Agora tenho muita ação acontecendo, e o único atraso parece ser uma queda de 1-3 fps ao jogar no nível mais complexo de um iPhone 4.
Ainda assim, decidi usar o Instruments para encontrar as funções que estavam ocupando mais tempo. Eu descobri que os problemas não estavam relacionados ao meu uso de UIViews . Em vez disso, chamava repetidamente o CGRectMake para determinados cálculos de detecção de colisão e carregava arquivos de imagem e áudio separadamente para determinadas classes que usam as mesmas imagens, em vez de tê-los de uma classe de armazenamento central.
Portanto, no final, você poderá obter um pequeno ganho usando o CoreGraphics, mas geralmente não valerá a pena ou poderá não ter nenhum efeito. A única vez em que uso o CoreGraphics é ao desenhar formas geométricas em vez de texto e imagens.
fonte