Respostas:
Você está procurando esta solução:
StaticDataTableViewController 2.0
https://github.com/xelvenone/StaticDataTableViewController
que pode mostrar / ocultar / recarregar qualquer célula estática com ou sem animação!
[self cell:self.outletToMyStaticCell1 setHidden:hide];
[self cell:self.outletToMyStaticCell2 setHidden:hide];
[self reloadDataAnimated:YES];
Nota para sempre usar somente (reloadDataAnimated: YES / NO) (não chame [self.tableView reloadData] diretamente)
Isso não usa a solução hacky com altura de 0 e permite animar a alteração e ocultar seções inteiras
IBOutletCollection
mas não vejo como isso faria diferença. Eu só baixei o código ontem, então não acho que seja uma versão antiga.
Para ocultar células estáticas no UITable:
Na classe delegada do controlador UITableView:
Objetivo-C:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell* cell = [super tableView:tableView cellForRowAtIndexPath:indexPath];
if(cell == self.cellYouWantToHide)
return 0; //set the hidden cell's height to 0
return [super tableView:tableView heightForRowAtIndexPath:indexPath];
}
Rápido:
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
var cell = super.tableView(tableView, cellForRowAtIndexPath: indexPath)
if cell == self.cellYouWantToHide {
return 0
}
return super.tableView(tableView, heightForRowAtIndexPath: indexPath)
}
Este método será chamado para cada célula na UITable. Depois que a chama para a célula que você deseja ocultar, definimos sua altura como 0. Identificamos a célula de destino criando uma saída para ela:
ClipToBounds
problema, você também pode definir a célula como oculta. Isso me pareceria mais limpo. ;-)
A melhor maneira é descrita no seguinte blog http://ali-reynolds.com/2013/06/29/hide-cells-in-static-table-view/
Projete sua visualização de tabela estática normalmente no criador de interface - completo com todas as células potencialmente ocultas. Mas há uma coisa que você deve fazer para cada célula em potencial que deseja ocultar - marque a propriedade “Clip subviews” da célula, caso contrário, o conteúdo da célula não desaparece quando você tenta ocultá-la (diminuindo sua altura - mais tarde).
SO - você tem um comutador em uma célula e o comutador deve ocultar e mostrar algumas células estáticas. Conecte-o a uma IBAction e faça isso:
[self.tableView beginUpdates]; [self.tableView endUpdates];
Isso fornece animações agradáveis para as células que aparecem e desaparecem. Agora implemente o seguinte método delegado de exibição de tabela:
- (float)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { if (indexPath.section == 1 && indexPath.row == 1) { // This is the cell to hide - change as you need // Show or hide cell if (self.mySwitch.on) { return 44; // Show the cell - adjust the height as you need } else { return 0; // Hide the cell } } return 44; }
E é isso. Gire o botão e a célula se oculta e reaparece com uma animação agradável e suave.
Minha solução segue uma direção semelhante à de Gareth, embora eu faça algumas coisas de maneira diferente.
Aqui vai:
1. Esconda as células
Não há como ocultar diretamente as células. UITableViewController
é a fonte de dados que fornece as células estáticas e, atualmente, não há como dizer "não forneça a célula x". Portanto, precisamos fornecer nossa própria fonte de dados, que delega para a UITableViewController
fim de obter as células estáticas.
O mais fácil é subclassificar UITableViewController
e substituir todos os métodos que precisam se comportar de maneira diferente ao ocultar células .
No caso mais simples (tabela de seção única, todas as células têm a mesma altura), isso seria assim:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [super tableView:tableView numberOfRowsInSection:section] - numberOfCellsHidden;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// Recalculate indexPath based on hidden cells
indexPath = [self offsetIndexPath:indexPath];
return [super tableView:tableView cellForRowAtIndexPath:indexPath];
}
- (NSIndexPath*)offsetIndexPath:(NSIndexPath*)indexPath
{
int offsetSection = indexPath.section; // Also offset section if you intend to hide whole sections
int numberOfCellsHiddenAbove = ... // Calculate how many cells are hidden above the given indexPath.row
int offsetRow = indexPath.row + numberOfCellsHiddenAbove;
return [NSIndexPath indexPathForRow:offsetRow inSection:offsetSection];
}
Se sua tabela tiver várias seções ou as células tiverem alturas diferentes, será necessário substituir mais métodos. O mesmo princípio se aplica aqui: você precisa compensar indexPath, seção e linha antes de delegar para super.
Lembre-se também de que o parâmetro indexPath para métodos como didSelectRowAtIndexPath:
será diferente para a mesma célula, dependendo do estado (ou seja, o número de células ocultas). Portanto, é provavelmente uma boa ideia sempre compensar qualquer parâmetro indexPath e trabalhar com esses valores.
2. Animar a mudança
Como Gareth já afirmou, você obtém grandes falhas se animar alterações usando o reloadSections:withRowAnimation:
método
Eu descobri que, se você ligar reloadData:
imediatamente depois, a animação será muito melhorada (apenas pequenas falhas). A tabela é exibida corretamente após a animação.
Então, o que estou fazendo é:
- (void)changeState
{
// Change state so cells are hidden/unhidden
...
// Reload all sections
NSIndexSet* reloadSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [self numberOfSectionsInTableView:tableView])];
[tableView reloadSections:reloadSet withRowAnimation:UITableViewRowAnimationAutomatic];
[tableView reloadData];
}
numberOfRowsInSection:
é chamado somente quando a tabela é carregada pela primeira vez. Quando eu chamo [self.tableView reloadData] - numberOfRowsInSection:
nunca é chamado novamente. Apenas cellForRowAtIndexPath:
é chamado. o que estou perdendo?
cellOneOutlet.hidden = true
agora substitua o método abaixo, verifique qual status da célula está oculto e retorne a altura 0 para essas células. Essa é uma das muitas maneiras pelas quais você pode ocultar qualquer célula no tableView estático rapidamente.
override func tableView(tableView: UITableView, heightForRowAtIndexPathindexPath: NSIndexPath) -> CGFloat
{
let tableViewCell = super.tableView(tableView,cellForRowAtIndexPath: indexPath)
if tableViewCell.hidden == true
{
return 0
}
else{
return super.tableView(tableView, heightForRowAtIndexPath: indexPath)
}
}
let tableViewCell = super.tableView(tableView,cellForRowAtIndexPath: indexPath)
. Presumo que seja substituído por let tableViewCell = tableView.cellForRow(at: indexPath as IndexPath)
.
UITableViewController
, não tenho UITableView
métodos de delegação. Para que ele seja chamado heightForRow
, também preciso ter outros métodos?
Eu vim com uma alternativa que realmente oculta seções e não as exclui. Tentei a abordagem do @ henning77, mas continuava tendo problemas quando alterava o número de seções do UITableView estático. Esse método funcionou muito bem para mim, mas estou tentando principalmente ocultar seções em vez de linhas. Estou removendo algumas linhas rapidamente, mas é muito mais confuso, então tentei agrupar as coisas em seções que preciso mostrar ou ocultar. Aqui está um exemplo de como estou ocultando seções:
Primeiro declaro uma propriedade NSMutableArray
@property (nonatomic, strong) NSMutableArray *hiddenSections;
No viewDidLoad (ou depois de consultar seus dados), você pode adicionar seções que deseja ocultar à matriz.
- (void)viewDidLoad
{
hiddenSections = [NSMutableArray new];
if(some piece of data is empty){
// Add index of section that should be hidden
[self.hiddenSections addObject:[NSNumber numberWithInt:1]];
}
... add as many sections to the array as needed
[self.tableView reloadData];
}
Em seguida, implemente os seguintes métodos de delegação do TableView
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
if([self.hiddenSections containsObject:[NSNumber numberWithInt:section]]){
return nil;
}
return [super tableView:tableView titleForHeaderInSection:section];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
if([self.hiddenSections containsObject:[NSNumber numberWithInt:indexPath.section]]){
return 0;
}
return [super tableView:tableView heightForRowAtIndexPath:[self offsetIndexPath:indexPath]];
}
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
if([self.hiddenSections containsObject:[NSNumber numberWithInt:indexPath.section]]){
[cell setHidden:YES];
}
}
Em seguida, defina a altura do cabeçalho e rodapé como 1 para seções ocultas porque você não pode definir a altura como 0. Isso causa um espaço adicional de 2 pixels, mas podemos compensar isso ajustando a altura do próximo cabeçalho visível.
-(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
CGFloat height = [super tableView:tableView heightForHeaderInSection:section];
if([self.hiddenSections containsObject:[NSNumber numberWithInt:section]]){
height = 1; // Can't be zero
}
else if([self tableView:tableView titleForHeaderInSection:section] == nil){ // Only adjust if title is nil
// Adjust height for previous hidden sections
CGFloat adjust = 0;
for(int i = (section - 1); i >= 0; i--){
if([self.hiddenSections containsObject:[NSNumber numberWithInt:i]]){
adjust = adjust + 2;
}
else {
break;
}
}
if(adjust > 0)
{
if(height == -1){
height = self.tableView.sectionHeaderHeight;
}
height = height - adjust;
if(height < 1){
height = 1;
}
}
}
return height;
}
-(CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
if([self.hiddenSections containsObject:[NSNumber numberWithInt:section]]){
return 1;
}
return [super tableView:tableView heightForFooterInSection:section];
}
Em seguida, se você tiver linhas específicas para ocultar, poderá ajustar o numberOfRowsInSection e quais linhas serão retornadas em cellForRowAtIndexPath. Neste exemplo, aqui eu tenho uma seção que possui três linhas em que três podem estar vazias e precisam ser removidas.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSInteger rows = [super tableView:tableView numberOfRowsInSection:section];
if(self.organization != nil){
if(section == 5){ // Contact
if([self.organization objectForKey:@"Phone"] == [NSNull null]){
rows--;
}
if([self.organization objectForKey:@"Email"] == [NSNull null]){
rows--;
}
if([self.organization objectForKey:@"City"] == [NSNull null]){
rows--;
}
}
}
return rows;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
return [super tableView:tableView cellForRowAtIndexPath:[self offsetIndexPath:indexPath]];
}
Use este offsetIndexPath para calcular o indexPath para linhas nas quais você está removendo condicionalmente as linhas. Não é necessário se você estiver ocultando apenas seções
- (NSIndexPath *)offsetIndexPath:(NSIndexPath*)indexPath
{
int row = indexPath.row;
if(self.organization != nil){
if(indexPath.section == 5){
// Adjust row to return based on which rows before are hidden
if(indexPath.row == 0 && [self.organization objectForKey:@"Phone"] == [NSNull null] && [self.organization objectForKey:@"Email"] != [NSNull null]){
row++;
}
else if(indexPath.row == 0 && [self.organization objectForKey:@"Phone"] == [NSNull null] && [self.organization objectForKey:@"Address"] != [NSNull null]){
row = row + 2;
}
else if(indexPath.row == 1 && [self.organization objectForKey:@"Phone"] != [NSNull null] && [self.organization objectForKey:@"Email"] == [NSNull null]){
row++;
}
else if(indexPath.row == 1 && [self.organization objectForKey:@"Phone"] == [NSNull null] && [self.organization objectForKey:@"Email"] != [NSNull null]){
row++;
}
}
}
NSIndexPath *offsetPath = [NSIndexPath indexPathForRow:row inSection:indexPath.section];
return offsetPath;
}
Existem muitos métodos a serem substituídos, mas o que eu gosto nessa abordagem é que ela é reutilizável. Configure a matriz hiddenSections, adicione-a e ela ocultará as seções corretas. Escondendo as linhas é um pouco mais complicado, mas possível. Não podemos simplesmente definir a altura das linhas que queremos ocultar para 0 se estivermos usando um UITableView agrupado porque as bordas não serão desenhadas corretamente.
NSMutableSet
em hiddenSections
vez disso. É muito mais rápido, pois você está testando principalmente a associação.
NSMutableSet
de hiddenSections
, embora eu entenda que o ponto da sua resposta foi mais conceitual do que exigente quanto ao tipo de estrutura de dados que você deve usar.
Acontece que você pode ocultar e mostrar células em um UITableView estático - e com animação. E não é tão difícil de realizar.
Vídeo do projeto de demonstração
A essência:
Use tableView:heightForRowAtIndexPath:
para especificar alturas de célula dinamicamente com base em algum estado.tableView.beginUpdates();tableView.endUpdates()
tableView.cellForRowAtIndexPath:
dentro tableView:heightForRowAtIndexPath:
. Use indexPaths em cache para diferenciar as células.Sim, é definitivamente possível, embora eu esteja lutando com o mesmo problema no momento. Consegui fazer com que as células se escondessem e tudo funcionasse bem, mas atualmente não posso fazer a coisa animar perfeitamente. Aqui está o que eu encontrei:
Estou ocultando linhas com base no estado de um botão ON / OFF na primeira linha da primeira seção. Se o interruptor estiver LIGADO, há 1 linha abaixo na mesma seção, caso contrário, existem 2 linhas diferentes.
Eu tenho um seletor chamado quando o comutador é alternado e defino uma variável para indicar em que estado estou. Depois, chamo:
[[self tableView] reloadData];
Eu substituo a função tableView: willDisplayCell: forRowAtIndexPath: e se a célula deveria estar oculta, faço isso:
[cell setHidden:YES];
Isso oculta a célula e seu conteúdo, mas não remove o espaço que ocupa.
Para remover o espaço, substitua a função tableView: heightForRowAtIndexPath: e retorne 0 para as linhas que devem estar ocultas.
Você também precisa substituir tableView: numberOfRowsInSection: e retornar o número de linhas nessa seção. Você precisa fazer algo estranho aqui para que, se sua tabela for um estilo agrupado, os cantos arredondados ocorram nas células corretas. Na minha tabela estática, há o conjunto completo de células para a seção; portanto, há a primeira célula que contém a opção, depois uma célula para as opções de estado ON e mais duas células para as opções de estado OFF, um total de 4 células. Quando a opção está ativada, tenho que retornar 4, isso inclui a opção oculta para que a última opção exibida tenha uma caixa arredondada. Quando a opção está desativada, as duas últimas opções não são exibidas, então eu retorno 2. Isso tudo parece desajeitado. Desculpe se isso não está muito claro, é difícil de descrever. Apenas para ilustrar a configuração, esta é a construção da seção da tabela no IB:
Portanto, quando a opção está ativada, a tabela relata duas linhas que são:
Quando a opção está DESLIGADA, a tabela reporta quatro linhas:
Essa abordagem não parece correta por várias razões, é o máximo que eu tenho com a minha experiência até agora; então, deixe-me saber se você encontrar uma maneira melhor. Os problemas que observei até agora são:
Parece errado dizer à tabela que o número de linhas é diferente do que está presumivelmente contido nos dados subjacentes.
Não consigo animar a mudança. Eu tentei usar tableView: reloadSections: withRowAnimation: em vez de reloadData e os resultados não parecem fazer sentido, ainda estou tentando fazer isso funcionar. Atualmente, o que parece acontecer é que o tableView não atualiza as linhas corretas, permanecendo oculto que deve ser exibido e um nulo é deixado na primeira linha. Eu acho que isso pode estar relacionado ao primeiro ponto sobre os dados subjacentes.
Espero que alguém possa sugerir métodos alternativos ou talvez como estender a animação, mas talvez isso o ajude a começar. Minhas desculpas pela falta de hiperlinks para funções, eu os coloquei, mas eles foram rejeitados pelo filtro de spam porque eu sou um usuário relativamente novo.
[[self tableView] reloadData];
mais uma vez depois de esconder as células
return [super tableView:tableView cellForRowAtIndexPath:indexPath];
na UITableViewController
subclasse para a criação de células estáticas. Caminhos de índice são indexados estático - não dinâmica ...
Conforme resposta de Justas, mas para Swift 4:
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
let cell = super.tableView(tableView, cellForRowAt: indexPath)
if cell == self.cellYouWantToHide {
return 0
}
return super.tableView(tableView, heightForRowAt: indexPath)
}
tableView.reloadRows(at:, with:)
atualizar as células se você alterar a altura enquanto a linha já estiver visível.
Ok, depois de algumas tentativas, tenho uma resposta não comum. Estou usando a variável "isHidden" ou "hidden" para verificar se esta célula deve estar oculta.
crie um IBOutlet para o seu controlador de exibição.
@IBOutlet weak var myCell: UITableViewCell!
Atualize o myCell
em sua função personalizada, por exemplo, você pode adicioná-lo em viewDidLoad:
override func viewDidLoad() {
super.viewDidLoad()
self.myCell.isHidden = true
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
let cell = super.tableView(tableView, cellForRowAt: indexPath)
guard !cell.isHidden else {
return 0
}
return super.tableView(tableView, heightForRowAt: indexPath)
}
Isso reduzirá sua lógica no método delegado, e você só precisará se concentrar nos requisitos de negócios.
As respostas acima que ocultam / mostram células, alteram rowHeight ou interferem nas restrições de layout automático não funcionaram para mim devido a problemas de layout automático. O código tornou-se intolerável.
Para uma tabela estática simples, o que funcionou melhor para mim foi:
Aqui está um exemplo do meu controlador de exibição de tabela:
@IBOutlet weak var titleCell: UITableViewCell!
@IBOutlet weak var nagCell: UITableViewCell!
@IBOutlet weak var categoryCell: UITableViewCell!
var cellsToShow: [UITableViewCell] = []
override func viewDidLoad() {
super.viewDidLoad()
determinCellsToShow()
}
func determinCellsToShow() {
if detail!.duration.type != nil {
cellsToShow = [titleCell, nagCell, categoryCell]
}
else {
cellsToShow = [titleCell, categoryCell]
}
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
return cellsToShow[indexPath.row]
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return cellsToShow.count
}
Para o iOS 11, descobri que uma versão modificada da resposta de Mohamed Saleh funcionava melhor, com algumas melhorias baseadas na documentação da Apple. Ele é animado, evita hacks feios ou valores codificados e usa alturas de linha já definidas no Interface Builder .
O conceito básico é definir a altura da linha como 0 para todas as linhas ocultas. Em seguida, use tableView.performBatchUpdates
para acionar uma animação que funcione de forma consistente.
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if indexPath == indexPathOfHiddenCell {
if cellIsHidden {
return 0
}
}
// Calling super will use the height set in your storyboard, avoiding hardcoded values
return super.tableView(tableView, heightForRowAt: indexPath)
}
Você quer ter certeza cellIsHidden
e indexPathOfHiddenCell
está configurado adequadamente para seu caso de uso. Para o meu código, são propriedades no meu controlador de exibição de tabela.
Seja qual for o método que controla a visibilidade (provavelmente uma ação de botão ou didSelectRow
), alterne o estado cellIsHidden, dentro de um performBatchUpdates
bloco:
tableView.performBatchUpdates({
// Use self to capture for block
self.cellIsHidden = !self.cellIsHidden
}, completion: nil)
A Apple recomenda performBatchUpdates
mais beginUpdates
/endUpdates
sempre que possível.
Encontrei uma solução para animar células ocultas na tabela estática.
// Class for wrapping Objective-C block
typedef BOOL (^HidableCellVisibilityFunctor)();
@interface BlockExecutor : NSObject
@property (strong,nonatomic) HidableCellVisibilityFunctor block;
+ (BlockExecutor*)executorWithBlock:(HidableCellVisibilityFunctor)block;
@end
@implementation BlockExecutor
@synthesize block = _block;
+ (BlockExecutor*)executorWithBlock:(HidableCellVisibilityFunctor)block
{
BlockExecutor * executor = [[BlockExecutor alloc] init];
executor.block = block;
return executor;
}
@end
Apenas um dicionário adicional é necessário:
@interface MyTableViewController ()
@property (nonatomic) NSMutableDictionary * hidableCellsDict;
@property (weak, nonatomic) IBOutlet UISwitch * birthdaySwitch;
@end
E observe a implementação do MyTableViewController. Precisamos de dois métodos para converter indexPath entre índices visíveis e invisíveis ...
- (NSIndexPath*)recoverIndexPath:(NSIndexPath *)indexPath
{
int rowDelta = 0;
for (NSIndexPath * ip in [[self.hidableCellsDict allKeys] sortedArrayUsingSelector:@selector(compare:)])
{
BlockExecutor * executor = [self.hidableCellsDict objectForKey:ip];
if (ip.section == indexPath.section
&& ip.row <= indexPath.row + rowDelta
&& !executor.block())
{
rowDelta++;
}
}
return [NSIndexPath indexPathForRow:indexPath.row+rowDelta inSection:indexPath.section];
}
- (NSIndexPath*)mapToNewIndexPath:(NSIndexPath *)indexPath
{
int rowDelta = 0;
for (NSIndexPath * ip in [[self.hidableCellsDict allKeys] sortedArrayUsingSelector:@selector(compare:)])
{
BlockExecutor * executor = [self.hidableCellsDict objectForKey:ip];
if (ip.section == indexPath.section
&& ip.row < indexPath.row - rowDelta
&& !executor.block())
{
rowDelta++;
}
}
return [NSIndexPath indexPathForRow:indexPath.row-rowDelta inSection:indexPath.section];
}
Uma alteração da IBAction no valor do UISwitch:
- (IBAction)birthdaySwitchChanged:(id)sender
{
NSIndexPath * indexPath = [self mapToNewIndexPath:[NSIndexPath indexPathForRow:1 inSection:1]];
if (self.birthdaySwitch.on)
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
else
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
}
Alguns métodos UITableViewDataSource e UITableViewDelegate:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
int numberOfRows = [super tableView:tableView numberOfRowsInSection:section];
for (NSIndexPath * indexPath in [self.hidableCellsDict allKeys])
if (indexPath.section == section)
{
BlockExecutor * executor = [self.hidableCellsDict objectForKey:indexPath];
numberOfRows -= (executor.block()?0:1);
}
return numberOfRows;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
indexPath = [self recoverIndexPath:indexPath];
return [super tableView:tableView cellForRowAtIndexPath:indexPath];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
indexPath = [self recoverIndexPath:indexPath];
return [super tableView:tableView heightForRowAtIndexPath:indexPath];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// initializing dictionary
self.hidableCellsDict = [NSMutableDictionary dictionary];
[self.hidableCellsDict setObject:[BlockExecutor executorWithBlock:^(){return self.birthdaySwitch.on;}] forKey:[NSIndexPath indexPathForRow:1 inSection:1]];
}
- (void)viewDidUnload
{
[self setBirthdaySwitch:nil];
[super viewDidUnload];
}
@end
Resposta rápida :
Adicione o seguinte método no seu TableViewController:
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return indexPathOfCellYouWantToHide == indexPath ? 0 : super.tableView(tableView, heightForRowAtIndexPath: indexPath)
}
se o tableView tentar desenhar a célula que você deseja ocultar, ela não será exibida porque sua altura será definida como 0pt, graças ao método acima, todo o resto permanecerá inalterado.
Observe que indexPathOfCellYouWantToHide
pode ser alterado a qualquer momento :)
No Swift 2.2, eu combinei algumas respostas aqui.
Faça uma saída do storyboard para vincular ao seu staticCell.
@IBOutlet weak var updateStaticCell: UITableViewCell!
override func viewDidLoad() {
...
updateStaticCell.hidden = true
}
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
if indexPath.row == 0 {
return 0
} else {
return super.tableView(tableView, heightForRowAtIndexPath: indexPath)
}
}
Quero ocultar minha primeira célula e defino a altura como 0, conforme descrito acima.
Swift 4:
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
var height = super.tableView(tableView, heightForRowAt: indexPath)
if (indexPath.row == HIDDENROW) {
height = 0.0
}
return height
}
Para o cenário mais fácil ao ocultar células na parte inferior da exibição da tabela, você pode ajustar o contentInset do tableView após ocultar a célula:
- (void)adjustBottomInsetForHiddenSections:(NSInteger)numberOfHiddenSections
{
CGFloat bottomInset = numberOfHiddenSections * 44.0; // or any other 'magic number
self.tableView.contentInset = UIEdgeInsetsMake(self.tableView.contentInset.top, self.tableView.contentInset.left, -bottomInset, self.tableView.contentInset.right);
}
Esta é uma nova maneira de fazer isso usando https://github.com/k06a/ABStaticTableViewController
NSIndexPath *ip = [NSIndexPath indexPathForRow:1 section:1];
[self deleteRowsAtIndexPaths:@[ip] withRowAnimation:UITableViewRowAnimationFade]
A solução do k06a ( https://github.com/k06a/ABStaticTableViewController ) é melhor porque oculta toda a seção, incluindo cabeçalhos e rodapés de células, onde esta solução ( https://github.com/peterpaulis/StaticDataTableViewController ) oculta tudo, exceto o rodapé.
EDITAR
Acabei de encontrar uma solução, se você deseja ocultar o rodapé StaticDataTableViewController
. É isso que você precisa copiar no arquivo StaticTableViewController.m:
- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section {
if ([tableView.dataSource tableView:tableView numberOfRowsInSection:section] == 0) {
return nil;
} else {
return [super tableView:tableView titleForFooterInSection:section];
}
}
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {
CGFloat height = [super tableView:tableView heightForFooterInSection:section];
if (self.originalTable == nil) {
return height;
}
if (!self.hideSectionsWithHiddenRows) {
return height;
}
OriginalSection * os = self.originalTable.sections[section];
if ([os numberOfVissibleRows] == 0) {
//return 0;
return CGFLOAT_MIN;
} else {
return height;
}
//return 0;
return CGFLOAT_MIN;
}
Certamente você pode. Primeiro, retorne ao número do número de células que você deseja exibir no tableView e ligue super
para obter determinada célula do storyboard e devolva-a para o tableView:
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.mode.numberOfCells()
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = super.tableView(tableView, cellForRowAtIndexPath: self.mode.indexPathForIndexPath(indexPath))
return cell
}
Se suas células tiverem hieght diferente, devolva-o também:
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return super.tableView(tableView, heightForRowAtIndexPath: self.mode.indexPathForIndexPath(indexPath))
}
Além da solução @Saleh Masum:
Se você receber erros de layout automático , poderá remover as restrições dotableViewCell.contentView
Swift 3:
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
let tableViewCell = super.tableView(tableView, cellForRowAt: indexPath)
if tableViewCell.isHidden == true
{
tableViewCell.contentView.removeConstraints(tableViewCell.contentView.constraints)
return 0
}
else{
return super.tableView(tableView, heightForRowAt: indexPath)
}
}
Esta solução depende do fluxo do seu aplicativo . Se você deseja mostrar / ocultar a célula na mesma instância do controlador de exibição, talvez essa não seja a melhor opção, pois remove as restrições .
Eu tenho uma maneira melhor de ocultar células estáticas e até seções dinamicamente sem hacks.
Definir a altura da linha como 0 pode ocultar uma linha, mas isso não funciona se você deseja ocultar uma seção inteira que conterá alguns espaços, mesmo que você oculte todas as linhas.
Minha abordagem é criar uma matriz de seções de células estáticas. Em seguida, o conteúdo da visualização da tabela será direcionado pela matriz de seção.
Aqui está um código de exemplo:
var tableSections = [[UITableViewCell]]()
private func configTableSections() {
// seciton A
tableSections.append([self.cell1InSectionA, self.cell2InSectionA])
// section B
if shouldShowSectionB {
tableSections.append([self.cell1InSectionB, self.cell2InSectionB])
}
// section C
if shouldShowCell1InSectionC {
tableSections.append([self.cell1InSectionC, self.cell2InSectionC, self.cell3InSectionC])
} else {
tableSections.append([self.cell2InSectionC, self.cell3InSectionC])
}
}
func numberOfSections(in tableView: UITableView) -> Int {
return tableSections.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tableSections[section].count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
return tableSections[indexPath.section][indexPath.row]
}
Dessa forma, você pode reunir todo o seu código de configuração sem precisar escrever o código desagradável para calcular o número de linhas e seções. E, claro, não há 0
mais alturas.
Este código também é muito fácil de manter. Por exemplo, se você deseja adicionar / remover mais células ou seções.
Da mesma forma, você pode criar uma matriz de título de cabeçalho de seção e matriz de título de rodapé de seção para configurar seus títulos de seção dinamicamente.