iOS8 - restrições sugerem ambiguamente uma altura de zero

100

Alguém tem alguma ideia de como depurar isso?

Aviso apenas uma vez: detectado um caso em que as restrições sugerem ambiguamente uma altura de zero para a visualização do conteúdo de uma célula do tableview. Estamos considerando o colapso não intencional e usando a altura padrão.

As linhas têm uma altura fixa definida por

- (CGFloat)tableView:(UITableView *)tableView 
           heightForRowAtIndexPath:(NSIndexPath *)indexPath{
   return 34.0;
}

E todos constraintsparecem estar felizes ...

Chris
fonte

Respostas:

129

Forçar uma altura de retorno e uma altura estimada fez o aviso desaparecer no meu caso.

- (CGFloat)tableView:(UITableView *)tableView 
           estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath {
    return 44;
}

- (CGFloat)tableView:(UITableView *)tableView 
           heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    return 44;
}

Outra solução onde você não precisa das duas substituições é simplesmente usar self.tableView.rowHeight = 44;em seu loadViewmétodo ou init.

FBronner
fonte
1
Tenho várias linhas de tipo na seção e apenas uma delas tem altura dinâmica. então não está funcionando
Raj Aggrawal
Se definirmos a altura padrão no xib / storyboard, não precisamos implementar esses métodos.
Satyam de
77

O que também pode ser feito é adicionar restrições verticais da parte superior e inferior da visualização do conteúdo. Isso deixará o autolayout feliz (porque agora ele sabe como calcular a altura da célula sozinho).

MonsieurDart
fonte
2
Isso funcionou para mim. Passei por todas as células do contêiner e verifiquei se pelo menos uma subvisualização tinha uma restrição "espaço superior para contêiner" e "espaço inferior para contêiner".
Rog182
7
Essa é a resposta certa para o iOS 8 ao usar células de exibição de tabela com autodimensionamento.
tsafrir
1
Você quer dizer restrições de elementos dentro da visualização do conteúdo até a parte superior e inferior da visualização do conteúdo?
Zack Shapiro
Tentei fazer isso, mas continuo recebendo avisos de restrição conflitantes.
Shirish Kumar,
2
Certifique-se de adicionar a restrição superior e inferior à visualização do conteúdo da célula, não a própria célula. Se você adicionar restrição à célula, o código ainda funcionará, mas tentará usar a altura de 0.
frin
26

Se você estiver usando restrições autoLayout e UITableViewAutomaticDimension, este erro não é um problema errôneo a ser descartado substituindo sua altura no código. Isso significa que determinar a altura da célula automaticamente não está funcionando porque você não tem as restrições verticais necessárias.

Se você é como eu e estava recebendo este erro e precisava de ajuda para identificar qual célula estava gerando o erro, você pode adicionar a seguinte linha logo antes do retorno de seu método 'heightforRowAtIndexPath'.

NSLog(@"Section %ld Row %ld", (long)[indexPath section], (long)[indexPath row]);

Isso imprimirá uma longa lista de seções e linhas, mas o erro aparecerá imediatamente após a célula específica que está causando o erro, e você pode identificar rapidamente qual célula está causando o problema e corrigir suas restrições de acordo. Isso é particularmente útil para células estáticas. Substituir a altura por um número inserido manualmente funcionará se você não estiver usando autoLayout e alturas de células automáticas, mas irá essencialmente desativar esses recursos, o que é uma solução muito pobre se for algo que você está tentando utilizar.

Se você não estava usando o método 'heightForRowAtIndexPath' anteriormente, mas deseja depurar esse erro sem desfazer a configuração UITableViewAutomaticDimension, basta adicionar ao seu código:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    NSLog(@"Section %ld Row %ld", (long)[indexPath section], (long)[indexPath row]);
    return UITableViewAutomaticDimension;
}
user2898617
fonte
Muito obrigado. Isso me ajudou muito. A princípio pensei que o problema era com outra célula de exibição de tabela. Depois de depurar, descobriu-se que o problema estava em outro.
akozin,
Eu gostaria de fazer isso, mas a seção longa e a linha não foram identificadas. Você poderia esclarecer o que deveria ser no Swift?
DrWhat
9

Parece haver um bug no XCode 6.1 que causa esse problema se usar o layout automático e você não especificar um valor para a Altura da Linha para cada Célula de Visualização de Tabela, mas em vez disso, você deixa o valor "padrão". Basta marcar a caixa de seleção "Personalizar" ao lado da Altura da linha, para cada célula, para que o aviso desapareça.

ltm
fonte
2
Se você estiver usando células de autodimensionamento, será necessário deixar a altura da linha definida como "padrão".
phatmann
1
Isso resolveu o aviso. Mas eu acredito que só aparece ao usar células estáticas em TableView
MontiRabbit
1
@phatmann Este problema só aparece para células estáticas, portanto, as células não devem ser autodimensionadas.
ltm
@ltm as células autodimensionadas podem não ser úteis, em células estáticas, se o usuário tiver texto aumentado, talvez? (Você sabe, em acessibilidade nas configurações do iPhone)
Byron Coetsee
Eu acho que não é um bug, pode ser um problema com as restrições verticais, elas têm que descrever completamente a altura da célula, para tableviews com dimensão automática pelo menos.
juanjo
3

Sim, você obtém todas as restrições "felizes", mesmo no caso de ter apenas restrições horizontais para itens na célula de exibição de tabela. Eu tive o mesmo problema. Você também precisa adicionar restrições verticais. Fazendo isso, esse aviso irá embora.

Juraj Antas
fonte
3

As restrições podem ser satisfeitas com o propósito de layout, mas não satisfeitas com o propósito de altura automática da linha. Um layout feliz significa que o conteúdo pode ser definido sem ambigüidade. Isso satisfaria as verificações no Interface Builder.

Um layout feliz para altura automática da linha significa que, além do acima, você também está incluindo restrições na parte inferior da célula.

Mais aqui: detectado um caso em que as restrições sugerem ambiguamente uma altura de zero

Woodster
fonte
3

Usei Row Height 43 (ou <> 44) no inspetor de tamanho de Table View e o erro desapareceu. Usando 44, recebo o erro. Xcode versão 6.0.1.

- Esta resposta foi removida por um moderador, por favor, não, isso corrige o problema. Isso RESOLVE o problema para mim e pode resolver para outras pessoas também. Então, você poderia fazer a gentileza de não excluí-lo novamente.

teho
fonte
2

Não consegui remover o aviso, mas para fazer as restrições funcionarem, configurei a propriedade tableview, new to iOS8, estimatedRowHeightpara a altura fixa e removi a heightForRowAtIndexPathimplementação.

emir
fonte
Se não removeu o aviso, então é o sistema que está compensando a restrição ausente e configurando a altura da linha == para a propriedade cell.rowHeight. O aviso é sobre uma propriedade de autocura. Se for autocurada, isso significa que o problema não ocorreu?
Pedro Borges,
2

Se você está recebendo esse aviso, provavelmente é porque está usando layout automático e suas células não têm nenhuma restrição dentro delas.

Você deve parar de usar o layout automático ou implementar restrições que definam sem ambigüidade a altura das células.

Você pode desligar o layout automático no construtor de interface desmarcando a opção "Usar layout automático" no inspetor de arquivos à direita.

Se você optar por usar o layout automático e a altura das células for fixa, a implementação das restrições apropriadas deve ser fácil. Basta adicionar restrições de altura para subvisualizações da visão de conteúdo da célula e implementar restrições de espaço vertical entre as subvisualizações e entre as subvisualizações e a visão de conteúdo. Por exemplo, se sua célula tiver um rótulo, isso funcionaria:

Restrições verticais

  1. Restrição de espaço vertical entre o topo da visualização do conteúdo e o topo do rótulo
  2. Restrição de altura fixa da etiqueta
  3. Restrição de espaço vertical entre a parte inferior do rótulo e a parte inferior da visualização do conteúdo

Restrições horizontais

  1. Restrição de espaço horizontal entre a borda dianteira da visualização do conteúdo e a borda dianteira do rótulo
  2. Restrição de largura fixa da etiqueta
  3. Restrição de espaço horizontal entre a borda posterior do rótulo e a borda posterior da visualização do conteúdo
wrightak
fonte
Estou usando restrições e todos parecem felizes, conforme mencionado na pergunta.
Chris,
Essas restrições são para as subvisualizações da visão de conteúdo da célula? Como eles se parecem? É possível que você tenha algumas células diferentes? Se você está definindo as células para ter uma altura fixa usando as soluções de Frederic Bonner, as restrições estão sendo substituídas.
Wrightak
1

Você pode usar o AutoLayout para calcular a altura certa para você. Aqui está uma boa postagem sobre Dynamic Cell Height no iOS 8: http://natashatherobot.com/ios-8-self-sizing-table-view-cells-with-dynamic-type/

Ricardopereira
fonte
Eu gostaria que fosse tão simples. Adicionar essas duas linhas não corrigiu meu problema de dimensionamento automático, infelizmente
Zack Shapiro
1

No Swift, forçar uma altura de retorno corrigiu meu problema:

override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
    if(indexPath.row == 0){
       return CGFloat(131.0)
    }else if(indexPath.row == 8){
       return CGFloat(97.0)
    }else{
       return CGFloat(44.0)
    }
}
O rei da bruxaria
fonte
1

Para uma solução padrão complicada, sem restrições, sem estimar alturas ou excesso de engenharia do problema. Eu criei um projeto padrão, conectei o tableview, mas esqueci de colocar o delegado de altura no controlador de visualização . Para simplesmente fazer este aviso desaparecer, você precisa disso.

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
    return 44;
}

No controlador de visualização da sua tabela.

latenitecoder
fonte
1

Eu estava usando um mapView dentro de uitableviewcell. Mudei a altura da visualização do mapa para 1/3 do tamanho da tela do dispositivo. Eu tenho o mesmo erro. Corrigi o erro adicionando restrições ausentes à visualização de conteúdo do uitableviewcell.

1) Limpe as restrições contentView.

2) Defina Redefinir para constantes sugeridas para contentView.

insira a descrição da imagem aqui

3) Adicionar restrições ausentes - se houver

4) Certificamo-nos de que a visualização do conteúdo possui todas as restrições necessárias. insira a descrição da imagem aqui

AG
fonte
0

No meu caso, é porque estou projetando a célula com xib e esqueci de adicionar esse arquivo xib ao destino.

Depois de adicionar esse arquivo xib ao destino, o problema desaparece

onmyway133
fonte
0

Embora as respostas nesta página que discutem a adição de restrições de altura ou o retorno manual de rowHeights como 44 em heightForRowAtIndexPath façam com que o aviso desapareça, elas são supérfluas porque este é um bug no Xcode visível pelo menos na versão 6.3.2 (6D2105).

Se você definir um ponto de interrupção em viewDidLoad, verá que self.tableView.rowHeight = -1 (UITableViewAutomaticDimension) mesmo se especificar uma altura de linha de 44 no storyboard. Isso ocorre porque a Apple assume incorretamente que você deseja alturas de linha dinâmicas se deixar a altura de linha em 44, porque eles não forneceram um sinalizador para você especificar sua preferência.

Aqui estão algumas soluções possíveis e seus resultados:

  • Defina a altura da linha para 43 ou 45 no storyboard (funciona).

  • Retorne manualmente uma altura de 44 em heightForRowAtIndexPath (funciona).

  • Adicione restrições de altura entre os elementos UITableViewCell e seu contentView (funciona).

Infelizmente, essas soluções exigem que você altere seu design, adicione restrições desnecessárias ou adicione código desnecessário para contornar um bug. Eu tentei (o que pensei ser) a solução mais simples:

  • Defina a altura de cada UITableViewCell para 44 (personalizado) no storyboard (falha).

Eu realmente queria uma solução de storyboard pura para isso, então finalmente tentei:

  • Adicione um atributo de tempo de execução definido pelo usuário ao UITableView no storyboard e nomeie o UITableView com uma nota sobre como seu rowHeight está sendo definido para que futuros desenvolvedores possam encontrá-lo: (funciona):

insira a descrição da imagem aqui

insira a descrição da imagem aqui

Esses bugs são muito comuns no desenvolvimento do iOS e forçam os desenvolvedores a gastar tempo excessivo pesando as ramificações de como suas soluções afetarão a manutenção a longo prazo.

Já que encontrar uma solução conceitualmente correta que seja sustentável e não pareça ofuscada é tão difícil de entender, e presumir que a Apple consertará o bug e que 44 será a altura padrão da linha em um futuro próximo, então a restrição ou definida pelo usuário as soluções de atributo de tempo de execução são provavelmente as mais fáceis de manter.

Zack Morris
fonte
0

Há duas coisas importantes acontecendo aqui, eu acho.

1) É super fácil fazer as restrições erradas se você estiver pressionando Ctrl + arrastando. Portanto, verifique se você fez isso corretamente. Melhor usar a bandeja no lado esquerdo da tela para desenhar essas restrições.

2) Em vez de especificar o estimadoRowHeight em ViewDidLoad ou em outro lugar, use o método delegado

override func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {}

Isso resolveu o problema imediatamente para mim.

Greg
fonte
Por que você está usando override?
FractalDoctor
0

Também vi esse erro ao usar storyboards universais ou xibs. Se você negligenciar a especificação de restrições adequadas para a classe de tamanho Any x Any, vi este erro aparecer.

A Apple parece ter corrigido isso para iOS9. O erro só aconteceu em 8.4 para mim.

David Nix
fonte
0

Passei vários dias entre esse erro e outro erro no qual as restrições estavam sendo criadas (não tenho ideia de onde) que conflitava com as restrições que eu queria. Eu até o fiz funcionar em uma instância em que todas as propriedades visíveis eram idênticas às outras. A única solução que encontrei foi ir atômica - criar um arquivo inteiramente novo com o xib e começar a reconectar os pontos de venda copiando e colando o código antigo. Pode não ser a melhor solução, mas às vezes, se o problema não for visível, não há muito mais o que fazer. No mínimo, tornar-se atômico é uma boa maneira de revisar o que está acontecendo.

DrWhat
fonte