objective-c - iOS8:i vincoli suggeriscono ambiguamente un'altezza pari a zero





uitableview heightforrowatindexpath (15)


Sembra esserci un bug in XCode 6.1 che causa questo problema se si utilizza il layout automatico e non si specifica un valore per l'altezza della riga per ogni cella di visualizzazione tabella, ma si lascia invece il valore "predefinito". Semplicemente selezionando la casella di controllo "Personalizzato" accanto all'altezza della riga, per ogni cella, l'avviso scompare.

Qualcuno ha qualche idea su come eseguire il debug di questo?

Avviso solo una volta: rilevato un caso in cui i vincoli suggeriscono ambiguamente un'altezza pari a zero per la vista del contenuto di una cella tableview. Stiamo considerando il collasso involontario e utilizzando invece l'altezza standard.

Le file hanno un'altezza fissa come impostato da

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

E tutti i constraints sembrano essere felici ...




Ciò che si può fare è aggiungere i vincoli verticali dall'alto e dal basso della vista del contenuto. Questo renderà felice l'autolayout (perché ora sa come calcolare l'altezza della cellula).




Se utilizzi i vincoli AutoLayout e UITableViewAutomaticDimension, questo errore non è un problema errato da ignorare sovrascrivendo l'altezza nel codice. Significa che determinare automaticamente l'altezza della cella non funziona perché non hai i vincoli verticali appropriati necessari.

Se sei come me e ricevi questo errore e hai bisogno di aiuto per identificare quale cella ha generato l'errore, puoi aggiungere la seguente riga appena prima del ritorno del tuo metodo 'heightforRowAtIndexPath'.

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

Questo stamperà un lungo elenco di sezioni e righe, ma l'errore apparirà immediatamente dopo la cella specifica che sta causando l'errore, e potrai identificare rapidamente quale cella sta causando il problema e correggere i tuoi vincoli di conseguenza. Questo è particolarmente utile per le celle statiche. Sostituire l'altezza con un numero inserito manualmente funzionerà se non utilizzi autoLayout e altezze automatiche delle celle, ma essenzialmente disabiliterà queste funzionalità che è una soluzione molto scarsa se si tratta di qualcosa che stai tentando di utilizzare.

Se in precedenza non si utilizzava il metodo 'heightForRowAtIndexPath' ma si desidera eseguire il debug di questo errore senza annullare l'impostazione di UITableViewAutomaticDimension, è sufficiente aggiungerlo al codice:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    NSLog(@"Section %ld Row %ld", (long)[indexPath section], (long)[indexPath row]);
    return UITableViewAutomaticDimension;
}



Nel mio caso, è perché sto progettando la cella con xib, e ho dimenticato di aggiungere quel file xib alla destinazione.

Dopo aver aggiunto il file xib alla destinazione, il problema è scomparso




Per una correzione standard di bog, nessun vincolo, nessuna altezza di stima o sovrastima del problema. Ho creato un progetto predefinito, cablato il tableview ma ho dimenticato di mettere il delegato dell'altezza nel controller della vista . Per fare in modo che questo avviso vada via è necessario.

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

Nel controller di visualizzazione della tabella.




Mentre le risposte su questa pagina che trattano l'aggiunta di limiti di altezza o il ritorno manuale di rowHeights come 44 in heightForRowAtIndexPath fanno sì che l'avviso scompaia, sono superflui perché questo è un bug in Xcode visibile almeno nella versione 6.3.2 (6D2105).

Se si imposta un punto di interruzione in viewDidLoad, vedrete che self.tableView.rowHeight = -1 (UITableViewAutomaticDimension) anche se si specifica un'altezza di riga di 44 nello storyboard. Ciò è dovuto al fatto che Apple assume erroneamente che si desidera l'altezza delle righe dinamiche se si lascia l'altezza della riga a 44, perché non hanno fornito un flag per specificare la propria preferenza.

Ecco alcune possibili soluzioni e i loro risultati:

  • Imposta l'altezza della riga su 43 o 45 nello storyboard (funziona).

  • Restituisce manualmente un'altezza di 44 in heightForRowAtIndexPath (funziona).

  • Aggiungi limiti di altezza tra gli elementi di UITableViewCell e il suo contentView (funziona).

Sfortunatamente, queste soluzioni richiedono la modifica della progettazione, l'aggiunta di vincoli non necessari o l'aggiunta di codice non necessario per aggirare un bug. Ho provato (quello che pensavo di essere) la soluzione più semplice:

  • Imposta l'altezza di ogni UITableViewCell su 44 (Personalizzato) nello storyboard (non riesce).

Volevo davvero una pura soluzione per lo storyboard, quindi alla fine ho provato:

  • Aggiungi un attributo di runtime definito dall'utente a UITableView nello storyboard e chiama UITableView con una nota su come viene impostato rowHeight in modo che gli sviluppatori futuri possano trovarlo: (funziona):

Questi bug sono fin troppo comuni nello sviluppo di iOS e costringono gli sviluppatori a impiegare troppo tempo a soppesare le conseguenze di come le loro soluzioni influenzeranno la manutenibilità a lungo termine.

Dal momento che trovare una soluzione concettualmente corretta, che è manutenibile e non sembra offuscata, è così elusiva, e supponendo che Apple risolverà il bug e che 44 sarà l'altezza della riga predefinita per il prossimo futuro, allora il vincolo o definito dall'utente le soluzioni di attributo runtime sono probabilmente le più mantenibili.




Non sono riuscito a rimuovere l'avviso, ma per far funzionare i vincoli ho impostato la proprietà newview su iOS8, tableview EstimateRowHeight sull'altezza fissa e l'implementazione heightForRowAtIndexPath rimossa.




Ho usato Altezza riga 43 (o <> 44) nell'ispettore Dimensioni tabella e l'errore è scomparso. Usando 44 ottengo l'errore. Xcode versione 6.0.1.

- Questa risposta è stata rimossa da un moderatore, per favore non farlo, risolve il problema. Questo risolve il problema per me e può farlo anche per gli altri. Quindi potresti essere così gentile da non cancellarlo di nuovo.




Ci sono due cose importanti che accadono qui, penso.

1) È molto semplice rendere i vincoli sbagliati se si fa CTRL + trascinamento. Quindi, controlla di averlo fatto correttamente. Meglio usare il vassoio sul lato sinistro dello schermo per disegnare questi vincoli.

2) Invece di specificare il valore AverageRowHeight in ViewDidLoad o da qualche altra parte, utilizzare il metodo delegate

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

Questo ha risolto il problema subito per me.




Se ricevi questo avviso, è molto probabile perché stai utilizzando il layout automatico e le tue celle non hanno alcun vincolo al loro interno.

Dovresti smettere di usare il layout automatico o implementare i vincoli che definiscono senza ambiguità l'altezza delle celle.

Puoi disattivare il layout automatico nel generatore di interfacce deselezionando l'opzione "Usa il caricamento automatico" nella finestra di ispezione dei file a destra.

Se si sceglie di utilizzare il layout automatico e l'altezza delle celle è fissa, l'implementazione dei vincoli appropriati dovrebbe essere semplice. È sufficiente aggiungere vincoli di altezza per le visualizzazioni secondarie della vista del contenuto della cella e implementare i vincoli di spazio verticale tra le visualizzazioni secondarie e tra le visualizzazioni secondarie e la vista del contenuto. Ad esempio se la tua cella ha un'etichetta in esso, questo funzionerebbe:

Vincoli verticali

  1. Vincolo di spazio verticale tra la parte superiore della vista del contenuto e la parte superiore dell'etichetta
  2. Vincolo di altezza fisso dell'etichetta
  3. Vincolo di spazio verticale tra la parte inferiore dell'etichetta e la parte inferiore della vista del contenuto

Vincoli orizzontali

  1. Vincolo di spazio orizzontale tra il bordo anteriore della vista del contenuto e il bordo anteriore dell'etichetta
  2. Vincolo di larghezza dell'etichetta fisso
  3. Vincolo di spazio orizzontale tra il bordo finale dell'etichetta e il bordo finale della vista del contenuto



Sì, ottieni tutti i vincoli "felici" anche nel caso in cui hai solo vincoli orizzontali per gli elementi nella cella di visualizzazione tabella. Ho avuto lo stesso problema. È necessario aggiungere anche vincoli verticali. Facendo così, quell'avviso sparirà.




Forzare un'altezza di ritorno e un'altezza stimata ha fatto sparire l'avviso nel mio caso.

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

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

Un'altra soluzione in cui non è necessario utilizzare i due override è semplicemente utilizzare self.tableView.rowHeight = 44; nel tuo metodo loadView o init.




I vincoli possono essere felici ai fini del layout, ma non sono soddisfatti allo scopo dell'altezza automatica della riga. Un layout felice significherebbe che il contenuto può essere presentato senza ambiguità. Ciò soddisferebbe i controlli in Interface Builder.

Un layout felice per l'altezza automatica delle righe significherebbe che, oltre a quanto sopra, includerai anche i vincoli sul fondo della cella.

Altro qui: Rilevato un caso in cui i vincoli suggeriscono ambiguamente un'altezza pari a zero




In Swift forzando un'altezza di ritorno risolto il mio 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)
    }
}



Ecco perché stai ricevendo l'errore. Come per la documentazione di iOS 6.0, il riferimento alla classe UITableView afferma che dequeueReusableCellWithIdentifier: è disponibile in iOS 2.0 e versioni successive e dequeueReusableCellWithIdentifier:forIndexPath: è disponibile in iOS 6.0 e versioni successive.







objective-c uitableview ios8 heightforrowatindexpath