Desejo alterar o deslocamento da tabela quando a carga terminar e esse deslocamento depende do número de células carregadas na tabela.
De qualquer forma, no SDK é possível saber quando um carregamento da visualização da uitabl foi concluído? Não vejo nada nos delegados nem nos protocolos de fonte de dados.
Não posso usar a contagem das fontes de dados devido apenas ao carregamento das células visíveis.
ios
iphone
uitableview
Montenegro
fonte
fonte
Respostas:
Melhore para a resposta @RichX:
lastRow
pode ser ambos[tableView numberOfRowsInSection: 0] - 1
ou((NSIndexPath*)[[tableView indexPathsForVisibleRows] lastObject]).row
. Portanto, o código será:ATUALIZAÇÃO: Bem, o comentário de @ htafoya está certo. Se você deseja que esse código detecte o fim do carregamento de todos os dados da fonte, não seria, mas essa não é a pergunta original. Este código é para detectar quando todas as células que deveriam estar visíveis são exibidas.
willDisplayCell:
usado aqui para uma interface do usuário mais suave (a única célula geralmente é exibida rapidamente após awillDisplay:
chamada). Você também pode tentartableView:didEndDisplayingCell:
.fonte
viewForFooterInSection
método.Versão Swift 3 e 4 e 5:
fonte
Eu sempre uso esta solução muito simples:
fonte
[tableView numberOfRowsInSection: 0] - 1
. Você deve substituir0
pelo valor necessário. Mas esse não é o problema. O problema é que o UITableView carrega apenas visível. No entanto,((NSIndexPath*)[[tableView indexPathsForVisibleRows] lastObject]).row
resolve o problema.Aqui está outra opção que parece funcionar para mim. No método delegado viewForFooter, verifique se é a seção final e adicione seu código lá. Essa abordagem veio à mente depois de perceber que o willDisplayCell não conta com rodapés se você os tiver.
Acho que essa abordagem funciona melhor se você procura encontrar o carregamento final para o todo
UITableView
, e não simplesmente as células visíveis. Dependendo das suas necessidades, você pode querer apenas as células visíveis; nesse caso, a resposta do folex é uma boa rota.fonte
nil
detableView:viewForFooterInSection:
mexer com meu layout no iOS 7 usando o Layout automático.return CGRectMake(0,0,0,0);
self.tableView.sectionFooterHeight = 0
. De qualquer maneira, parece inserir uma visualização de rodapé de seção com uma altura de cerca de 10. Aposto que eu poderia corrigir isso adicionando uma restrição de altura 0 à visualização que retorno. De qualquer forma, estou bem porque realmente queria descobrir como iniciar o UITableView na última célula, mas vi isso primeiro.Solução Swift 2:
fonte
Usando API privada:
Usando API pública:
Um design melhor possível é adicionar as células visíveis a um conjunto; quando você precisar verificar se a tabela está carregada, poderá fazer um loop for em torno desse conjunto, por exemplo
fonte
Para a versão de resposta escolhida no Swift 3:
Eu precisava da variável isLoadingTableView porque queria ter certeza de que a tabela está sendo carregada antes de fazer uma seleção de célula padrão. Se você não incluir isso, toda vez que rolar a tabela, ele invocará seu código novamente.
fonte
A melhor abordagem que conheço é a resposta de Eric em: Seja notificado quando o UITableView terminar de solicitar dados?
Atualização: para que funcione, tenho que fazer essas chamadas
-tableView:cellForRowAtIndexPath:
fonte
Para saber quando uma visualização de tabela termina de carregar seu conteúdo, primeiro precisamos ter um entendimento básico de como as visualizações são colocadas na tela.
No ciclo de vida de um aplicativo, existem quatro momentos principais:
Os tempos 2 e 3 são totalmente separados. Por quê ? Por razões de desempenho, não queremos realizar todos os cálculos do momento 3 cada vez que uma modificação é feita.
Então, acho que você está enfrentando um caso como este:
O que há de errado aqui?
Como qualquer visualização, uma visualização de tabela recarrega seu conteúdo lentamente. Na verdade, se você ligar
reloadData
várias vezes, isso não criará problemas de desempenho. A exibição da tabela apenas recalcula o tamanho do conteúdo com base na implementação delegada e aguarda o momento 3 para carregar suas células. Esse tempo é chamado de passe de layout.Ok, como entrar no passe de layout?
Durante a aprovação do layout, o aplicativo calcula todos os quadros da hierarquia de visualizações. Para se envolver, você pode substituir os métodos dedicados
layoutSubviews
,updateLayoutConstraints
etc em aUIView
e os métodos equivalentes em uma subclasse do controlador de exibição.É exatamente isso que uma exibição de tabela faz. Ele substitui
layoutSubviews
e, com base na implementação delegada, adiciona ou remove células. Ele chamacellForRow
logo antes de adicionar e colocar uma nova célula,willDisplay
logo depois. Se você chamoureloadData
ou acabou de adicionar a exibição de tabela à hierarquia, a exibição de tabelas adiciona quantas células forem necessárias para preencher seu quadro nesse momento chave.Tudo bem, mas agora, como saber quando uma exibição de tabelas terminou de recarregar seu conteúdo?
Agora podemos reformular esta pergunta: como saber quando uma exibição de tabela terminou de exibir suas subvisões?
• A maneira mais fácil é entrar no layout da exibição da tabela:
Observe que esse método é chamado várias vezes no ciclo de vida da visualização da tabela. Devido ao comportamento de rolagem e desenfileiramento da exibição de tabela, as células são modificadas, removidas e adicionadas frequentemente. Mas funciona logo após o
super.layoutSubviews()
carregamento das células. Esta solução é equivalente a aguardar owillDisplay
evento do último caminho do índice. Este evento é chamado durante a execução delayoutSubviews
exibição da tabela para cada célula adicionada.• Outra maneira é ser chamado quando o aplicativo termina um passe de layout.
Conforme descrito na documentação , você pode usar uma opção do
UIView.animate(withDuration:completion)
:Essa solução funciona, mas a tela é atualizada uma vez entre o momento em que o layout é concluído e o horário em que o bloco é chamado. Isso é equivalente à
DispatchMain.async
solução, mas especificado.• Como alternativa, eu preferiria forçar o layout da exibição da tabela
Existe um método dedicado para forçar qualquer visualização a calcular imediatamente seus quadros de subvisão
layoutIfNeeded
:Tenha cuidado, no entanto, isso removerá o carregamento lento usado pelo sistema. Chamar esses métodos repetidamente pode criar problemas de desempenho. Verifique se eles não serão chamados antes que o quadro da visualização da tabela seja computado, caso contrário, a visualização da tabela será carregada novamente e você não será notificado.
Eu acho que não há solução perfeita. Classes de subclassificação podem levar a trubles. Um passe de layout começa de cima e vai para baixo, para que não seja fácil ser notificado quando todo o layout estiver pronto. E
layoutIfNeeded()
pode criar problemas de desempenho, etc. Mas conhecendo essas opções, você deve pensar em uma alternativa que atenda às suas necessidades.fonte
Aqui está como você faz isso no Swift 3:
fonte
aqui está como eu faço isso no Swift 3
fonte
Aqui está o que eu faria.
Na sua classe base (pode ser rootVC BaseVc etc),
A. Escreva um protocolo para enviar o retorno de chamada "DidFinishReloading".
B. Escreva um método genérico para recarregar a exibição da tabela.
Na implementação do método da classe base, chame reloadData seguido por delegateMethod com atraso.
Confirme o protocolo de conclusão de recarregamento em todos os controladores de exibição em que você precisa do retorno de chamada.
Referência: https://discussions.apple.com/thread/2598339?start=0&tstart=0
fonte
A resposta @folex está certa.
Mas falhará se o tableView tiver mais de uma seção exibida por vez.
fonte
No Swift, você pode fazer algo assim. A condição a seguir será verdadeira sempre que você chegar ao final da tabela
fonte
Sei que isso foi respondido, estou apenas adicionando uma recomendação.
Conforme a documentação a seguir
https://www.objc.io/issues/2-concurrency/thread-safe-class-design/
Corrigir problemas de tempo com dispatch_async é uma má ideia. Sugiro que devemos lidar com isso adicionando FLAG ou algo assim.
fonte
Se você tiver várias seções, veja como obter a última linha na última seção (Swift 3):
fonte
Acidentalmente, encontrei esta solução:
Você precisa definir o footerView antes de obter o contentSize, por exemplo, em viewDidLoad. Btw. definir o footeView permite excluir separadores "não utilizados"
fonte
Você está procurando o número total de itens que serão exibidos na tabela ou o total de itens atualmente visíveis? De qualquer maneira .. Eu acredito que o método 'viewDidLoad' é executado depois que todos os métodos da fonte de dados são chamados. No entanto, isso funcionará apenas no primeiro carregamento dos dados (se você estiver usando um único ViewController de alocação).
fonte
Estou copiando o código de Andrew e expandindo-o para explicar o caso em que você tem apenas 1 linha na tabela. Está funcionando até agora para mim!
NOTA: Estou apenas usando uma seção do código de Andrew, tenha isso em mente.
fonte
No iOS7.0x, a solução é um pouco diferente. Aqui está o que eu criei.
fonte
Objetivo C
Rápido
fonte
UICollectionView
até onde eu entendo.