Truques para melhorar o desempenho de rolagem do UITableView do iPhone?

89

Eu tenho um uitableview que carrega imagens razoavelmente grandes em cada célula e as alturas das células variam dependendo do tamanho da imagem. O desempenho de rolagem é decente, mas às vezes pode ser irregular.

Encontrei estas dicas no blog da FieryRobot:

glassy-scrolling-with-uitableview

mais rolagem vítrea com uitableview

Alguém tem alguma dica para melhorar o desempenho de rolagem do uitableview?

Jonah
fonte
Se você precisar armazenar em cache as alturas das células (que podem ser caras para calcular e também são usadas com frequência), dei um exemplo. Use-o apenas se for adequado à sua aplicação. stackoverflow.com/questions/1371223/…
Paul de Lange

Respostas:

156
  1. Armazene em cache a altura das linhas (a visualização da tabela pode solicitar isso com frequência)
  2. Crie um cache menos usado recentemente para as imagens usadas na tabela (e invalide todas as entradas inativas ao receber um aviso de memória)
  3. Desenhe tudo no UITableViewCell's drawRect:se possível, evite subvisualizações a todo custo (ou se você precisar da funcionalidade de acessibilidade padrão, as visualizações de conteúdo drawRect:)
  4. Torne sua UITableViewCellcamada opaca (o mesmo se aplica à visualização de conteúdo, se houver)
  5. Use a funcionalidade reusableCellIdentifier conforme recomendado pelos UITableViewexemplos / documentação
  6. Evite gradientes / efeitos gráficos complicados que não são pré-embutidos em UIImages
Rpetrich
fonte
5
Além disso, as imagens baixadas devem ser reduzidas ao tamanho de imageView antes de serem exibidas na célula!
Zoltán Matók de
4
Eu gostaria de adicionar a esta resposta uma das minhas experiências nos últimos anos - ter células transparentes provavelmente nunca é a causa do desempenho ruim de rolagem. Temos um aplicativo com células MUITO complicadas (mais de 20 subvisualizações) e é tudo transparente para mostrar o fundo. Com as otimizações adequadas, a transparência não faz diferença, mesmo em um 3GS. Na verdade, o que mais desacelerou o material foi o carregamento da ponta, antes que houvesse células suficientes para retirar da vista da tabela. Se estiver usando subvisualizações, apenas certifique-se de ter hierarquias eficientes e de não precisar usar drawRect.
Accatyyc
@Accatyyc, parece que estou com o mesmo problema. Há um pequeno atraso quando não há células suficientes para retirar da fila, quando 3-4 células são retiradas da fila, a rolagem é suave. Existe alguma maneira de pré-carregar células para que haja células para retirar da fila e não para carregar arquivos NIB durante a rolagem?
Tiois
@Tiois Claro que existe. Você precisa usar o método antigo de retirar da fila as células (não registre classes / pontas, mas crie-as se dequeueCellWithIdentifier: retorna nil). Desta forma, você pode criar um conjunto de células antes mesmo de sua visualização de tabela existir, por exemplo, criando 20 delas antes. Então, em vez de criar novos em cellForRowAtIndexPath :, você os extrai de seu próprio cache primeiro, até que esteja vazio.
Accatyyc
Estou usando UICollectionView e enfrentando o mesmo problema. No meu arquivo de ponta de célula customizada. Estou usando várias subvisualizações, incluindo UIwebView e UIImageView dentro de UIstackView vertical. quando eu rolar minha lista, as células reutilizadas levam um tempo significativo para reajustar seu tamanho e a rolagem parece muito irregular.
Mansuu ....
40
  1. Se você estiver criando uma subclasse UITableViewCell, não use um Nib, escreva-o em código. É muito mais rápido do que carregar arquivos Nib.
  2. Se estiver usando imagens, certifique-se de armazená-las em cache para não ter que carregar do arquivo mais de uma vez para cada uma (se você tiver memória - ficaria surpreso com a quantidade de espaço que as imagens ocupam).
  3. Torne o máximo possível de elementos opacos. Da mesma forma, tente não usar imagens com transparência.
Sapo Salsicha
fonte
3
não se preocupe ... eram trolls. Ótima resposta!
Steav
79
Os votos negativos foram provavelmente porque "evitar pontas" é um conselho ruim para melhorar o desempenho. Se você estiver reutilizando células, elas não serão reconstruídas a partir de pontas durante a rolagem.
Steven Fisher
6
Nibs são equivalentes em velocidade, ou um pouco mais rápidos com base na pesquisa Cocoa with Love. cocoawithlove.com/2010/03/…
MaxGabriel
@Steven Fisher usando Nib pode ser mais lento quando a tabela aloca e desaloca células, por exemplo - durante a rolagem rápida.
Sound Blaster
3
O uso de NIBs pode ser mais lento quando a célula está sendo construída . Se você estiver usando a reciclagem de células, haverá apenas células suficientes alocadas para preencher a tela; digamos, talvez 10 no máximo. Quando você está rolando, as células não são criadas. Eles são apenas reutilizados , não desalocados e realocados. E, é claro, não há custo para desalocar. Portanto, não, isso não é correto.
Steven Fisher
34

O desenvolvedor por trás do Tweetie escreveu extensivamente sobre isso e possui um código que demonstra como foi feito para aquele aplicativo. Basicamente, ele defende uma visão customizada por célula da tabela, e desenhando-a manualmente (ao invés de subvisualizar com Interface Builder, entre outras opções).

rolagem rápida no tweetie com uitableview

Além disso, a Apple atualizou seu próprio código de amostra para TableView em seus tutoriais TableViewSuite (talvez em resposta a isso?)

TableViewSuite

beno
fonte
1
Esta é uma solução incrível. Estou apenas curioso para saber como adicionaria um UIButton ao cellView? Ele está sendo desenhado no método drawRect?
Sukitha Udugamasooriya
1
@beno, seu link parece quebrado (o primeiro) alguma chance de colocar as mãos no artigo original?
apouche,
3
O artigo original pode ser lido aqui: web.archive.org/web/20100922230053/http://blog.atebits.com/2008/…
jverdi
adicionado link para arquivo da web porque a versão original não existe
Ralph Willgoss
1

O assassino de desempenho número 1 para a rolagem UITableView é desenhar sombras em qualquer camada de visualização de célula, então se o desempenho da rolagem é importante, não faça sombras, a menos que basicamente isso não desacelere seu thread principal.

pensei que isso tinha que ser dito, uma vez que nenhuma das respostas aceitas fazia menção a sombras e camadas. : +)

JackyJohnson
fonte
6
se os problemas são as sombras, adicione essas duas linhas de código e tudo funcionará perfeitamente self.layer.shouldRasterize = YES; self.layer.rasterizationScale = UIScreen.mainScreen.scale;
Pedro Romão
0

Qualquer problema com o UITableViewdesempenho de rolagem pode ser resolvido usando técnicas já descritas em outras respostas. No entanto, muitas vezes o desempenho lento é causado por algo inerentemente errôneo ou repetitivo.

O fato de que UITableViewreutiliza as células e o fato de que cada célula pode precisar de sua própria imagem - juntos torna a solução um pouco complexa. De como está sendo resolvido de forma geral, aqui eu resumo as coisas que devem ser cuidadas:

  1. Carregue dados na fonte de dados - de REST / banco de dados. Esta etapa deve ser executada em segundo plano, eventualmente usando dispatch_async junto com a fila GCD.
  2. Crie e inicialize objetos de modelo de dados relevantes e os coloque dentro de uma matriz
  3. [tableView reloaddata]
  4. Dentro cellForRowAtIndexPath, inclua o código que definirá os dados (texto) do objeto de modelo de dados correto da matriz.
  5. Agora, as imagens também podem ser na forma de URL, então esta etapa pode ser um pouco peculiar por causa da reutilização de células feita pelo table view. O cerne do fato é carregar mais uma vez a imagem do cache / URL do dispositivo usando a fila assíncrona e, em seguida, configurá-la para corrigir cell.image (qualquer que seja a propriedade da imagem da sua célula).

Para evitar problemas, consulte este tutorial sobre carregamento lento de imagens dentro da exibição de tabela.

Nirav Bhatt
fonte