2014-09-23 17 views
24

Sono nel bel mezzo dello sviluppo di un'app per iPhone e iPad. Supporta iOS6 e iOS7 e utilizza esclusivamente il layout automatico.Problemi di Autolayout con iOS8 con codice che funziona correttamente su iOS7

Questa settimana scorsa, quando Apple ha annunciato che iOS8 era pronto per la prima serata, ho aggiornato uno dei miei iPhone e un iPad entrambi in iOS8. Ho anche urtato il mio XCODE fino alla versione 6. Ho il 2 ° iPhone che ho lasciato su iOS7.

Ho generato nuovi eseguibili con Xcode 6 e mi sono addolorato vedere che i loro layout dello schermo erano incasinati quando sono stati eseguiti sui miei dispositivi con iOS8, ma comunque su iOS7. Questo è vero sia per i miei dispositivi fisici che per gli emulatori di Xcode.

Ci sono voluti molti scavi ma ora sono abbastanza chiaro su cosa sta succedendo, anche se non so perché.

In particolare, alcune operazioni di layout automatico non riescono per me su iOS8, ma stanno bene su iOS7.

Alcuni esempi che comportano un pulsante che sto immissione in una vista di fondo la cui dimensione è uguale alla dimensione dello schermo:

(1) Se chiedo layout automatico per posizionare centro orizzontale del pulsante (CX) pari al centro orizzontale della vista sottostante, il risultato è che il centro orizzontale del pulsante è posizionato sul bordo sinistro della vista sottostante.

(2) Se si chiede layout automatico per rendere la larghezza del pulsante uguale al 50% della larghezza della vista sottostante, non fornisce alcuna larghezza.

sono in grado di risolvere questi problemi nel modo seguente:

(1) chiedo layout automatico per posizionare il centro del pulsante uguale al bordo sinistro della vista di base più il 50% della larghezza dello schermo.

(2) Chiedo layout automatico per rendere la larghezza del pulsante pari al 50% della larghezza dello schermo.

Sto lentamente artigliando la mia strada, con soluzioni simili come queste, al codice di layout automatico che funziona per me sia su iOS7 che su iOS8. Ma mi sto davvero chiedendo cosa sta succedendo qui.

Sembra che il layout automatico non sia in grado di determinare le dimensioni della vista sottostante e quindi i calcoli del layout automatico che richiedono il fallimento di tali informazioni. Ma sa dove i bordi superiore e sinistro della vista sono così i calcoli basati su quei dati riusciti.

Questa è una grande app e ho scritto molte centinaia di linee di codice di layout automatico per iOS6 e iOS7 che funzionano perfettamente per me.

Sono stato a modificare e provare le cose ora con iOS8 per tre giorni e non sono più saggio di quanto fossi quando ho iniziato.

Chiunque ha suggerimenti o pensieri su quale potrebbe essere il problema qui?

+0

Sono sulla stessa barca. In ogni caso, sembra che la larghezza della vista sottostante sia 0 all'inizio della larghezza, quindi quando hai detto al centro X del pulsante di essere il centro X della vista sottostante, il pulsante appare sul lato sinistro. – Zhang

+1

sì, e da quello che posso vedere finora, una volta che inizio a posizionare i controlli sulla vista, posso utilizzare tutte le diverse varianti delle relazioni di layout automatico tra quei controlli. Ad esempio, il centro orizzontale di un pulsante può essere allineato con un altro senza problemi. – Gallymon

+0

Vorrei anche menzionare che non sto usando IB. Tutto il mio codice di layout automatico viene realizzato costruendo direttamente NSLayoutConstraint/s. L'ho sempre fatto in questo modo e ha funzionato perfettamente su iOS7. – Gallymon

risposta

3

Potreste trovare le risposte a questa domanda utile: UICollectionView cell subviews do not resize

Nella maggior parte dei casi le opere in iOS7 ma non su iOS problemi di layout 8 auto sembrano derivare dalla vista di root non essendo dimensionato correttamente in iOS 8, in particolare quando impostiamo translatorsAutoresizingMaskIntoConstraints su NO. Per i miei punti di vista sono stato in grado di impostare il frame della vista radice in layoutSubviews (o qualsiasi inizializzatore appropriato che abbia i limiti corretti) e questo ha risolto il problema.

self.contentView.frame = CGRectInset(self.bounds, 0, 0); 

Come mostrato nella risposta di cui sopra, si potrebbe anche fare

self.contentView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; 

e poi girare di nuovo a translatesAutoresizingMaskIntoConstraints NO prima di iniziare a impostare i propri vincoli nel codice.

Sicuramente odio che così tanto del nostro tempo è preso con questi fastidiosi trucchi.

+0

Praneeth, grazie per questo. L'ho provato ma non influisce sul problema che sto avendo. – Gallymon

+0

Hmm, mi dispiace sentire che non ha aiutato. Nel mio caso ho avuto un mix di vincoli IB e quindi aggiustamenti nel codice in fase di esecuzione e questo ha risolto il mio problema. In bocca al lupo. –

11

@robmayoff ha una grande risposta per questo: https://stackoverflow.com/a/26066992/1424669

In sostanza, in iOS 8 non è più possibile chiamare setNeedsUpdateConstraints e setNeedsLayout su una visione e si aspettano i vincoli di subviews da aggiornare.

È necessario chiamare questi metodi sulla vista il cui vincolo sta cambiando. Questo è retrocompatibile con iOS7.

ESEMPIO:

Supponiamo di avere un ViewController con vista radice self.view e una visualizzazione secondaria chiamato containerView. containerView ha un NSLayoutConstraint collegato che si desidera modificare (in questo caso, lo spazio in alto).

In iOS7 è possibile aggiornare tutti i vincoli in un VC richiedendo un nuovo layout per la vista root:

self.containerView_TopSpace.constant = 0; 
[self.view setNeedsUpdateConstraints]; 
[self.view setNeedsLayout]; 

In iOS 8 è necessario richiedere layout sul containerView:

self.containerView_TopSpace.constant = 0; 
[self.containerView setNeedsUpdateConstraints]; 
[self.containerView setNeedsLayout]; 
+0

BFar, questa è una buona notizia e ha senso. Non vedo l'ora di provarlo e vedere se riesco a risolvere questo problema. – Gallymon

+0

@BFar Per favore, puoi mettere insieme un semplice progetto di esempio che mostri questo problema (ad esempio funziona su 7 SDK, ma non su 8 SDK) e poi file un radar e condividi il radar #? – smileyborg

+0

BFar, ho provato le idee di robmayoff ma non sembrano essere correlate al mio problema. Ora ho una soluzione legale per cui sto facendo pressioni. Grazie! – Gallymon

0

In il mio caso, il problema relativo ai vincoli etichettati UIView-Encapsulated-Layout-Width e UIView-Encapsulated-Layout-Height. Quando li ho rimossi, tutto si comportava come se la mia vista fosse di dimensioni zero, con tutto centrato nell'angolo in alto a sinistra dello schermo. Quando li ho lasciati, i nuovi vincoli hanno funzionato come previsto. Ho anche mantenuto i vincoli con l'etichetta _UILayoutSupportConstraint.

Problemi correlati