2015-09-02 8 views
5

Cercando di abbattere un problema che ho avuto per un po 'oraCome determinare dimensioni UIView prima viewDidAppear della sua ViewController

Sfondo

Supponiamo cerco di calcolare un UIImage che dovrebbe adattarsi perfettamente una UIImageView, che è strutturata con vincoli nello storyboard.

Il contenuto di imageView non deve essere riempito/adattato ... ma si inserisce perfettamente nel telaio. Pertanto Ho un metodo nel mio viewController

- (UIImage *)calculatedImageForRect:(CGRect)imageRect 

Problema

voglio fare in modo, che l'ImageView già contiene l'immagine corretta non appena la vista diventa visibile, quindi anche nel corso di una semplice spingere la transizione. Inoltre, non voglio generare UIImage più volte, poiché è relativamente costoso.

Questo diventa particolarmente interessante con dispositivi come l'iPhone6 ​​plus, che hanno una risoluzione dello schermo diversa

ovviamente a viewDidLoad i frame non sono impostati correttamente. A quel punto i fotogrammi sono impostati come nell'anteprima dello storyboard, ad es. setup per rappresentare la risoluzione IPhone5. Lo stesso è vero per viewWillAppear. Qui il telaio sarebbe ad es. essere (10,10,300,100) < - chiamiamolo mal-frame

Sulla viewDidAppear il telaio è corretta (10,10,394,100) = il corretto -frame < - larghezza invece di 320 punti, l'iPhone6Plus ha 414 punti. Tuttavia, qui è troppo tardi, poiché la vista è già visibile e l'impostazione dell'immagine risulterebbe in uno sfarfallio (immagine vuota> nuova immagine generata).

so il momento giusto per lavorare con la larghezza è la viewDidLayoutSubviews, che viene dapprima chiamato con il errata telaio almeno una volta, quindi in un punto con il corretto -frame. Ma, come ho detto, non voglio generare l'immagine più volte, quindi ecco il dilemma:

Come posso determinare il destro del telaio prima che sia visibile?

Naturalmente potrei calcolare la giusta cornice dalla risoluzione [UIScreen mainScreen] lavorando con le finali & vincoli di spicco del UIImageView, ma ci si sente sporca.

+0

Quindi l'essenza della tua domanda è che vuoi capire come essere avvisato quando una particolare vista nella tua gerarchia di vista (in questo caso una UIImageView) viene finalmente impostata sulla sua cornice corretta, ma prima di renderla sullo schermo? – algal

+0

Sì, questo è esattamente quello che voglio sapere – MarkHim

risposta

7

Il motivo per cui non è possibile utilizzare viewDidLayoutSubviews è che, come dici tu, può essere chiamato più di una volta. Questo vale anche per layoutSubviews.

Perché è questo? Una ragione è che è perché il layout basato su vincoli è un processo iterativo, che può coinvolgere più passaggi. Ad esempio, suppongo di forzare il layout della vista V, che contiene nella sua vista gerarchia una sottoview W, che contiene una sottoview X. Il primo calcolo Auto Layout del layout di X può modificare i vincoli che richiedono quindi un ricalcolo di W , che richiede quindi un ricalcolo di X.Questo è fondamentalmente diverso dal layout con le maschere di ridimensionamento automatico, che è dall'alto verso il basso, in modo che la vista esterna imponga sempre il layout della sua sottoview.

Tuttavia, I credo (ma non sono sicuro al 100%) che, se tutto il codice di layout è implementato correttamente, questi passaggi di layout multipli dovrebbero tutti avvenire entro un giro del ciclo di esecuzione. Cioè, quando si avvia questo processo chiamando layoutIfNeeded per forzare il layout su V, allora si può essere sicuri che il layout di layout automatico sia passato a e che W2 abbia completato, una volta restituito layoutIfNeeded. I contrassegni "need layout" o "need update vincint" saranno lasciati sporchi in attesa del prossimo turno del ciclo di esecuzione per completare il lavoro.

Questo potrebbe indicare la strada verso la soluzione. Se imposti un layout iniziale della vista di livello superiore nella tua gerarchia (ad esempio la vista root del controller di visualizzazione su cui stai eseguendo la transizione), al termine di tale passaggio di layout lo UIImageView avrà una cornice corretta e puoi utilizzarlo cornice per generare la tua immagine.

In sostanza, invece di eseguire il layout all'ultimo momento, si sta costringendo a farlo in precedenza. Quindi puoi sapere quando è finito, dal momento che è stato avviato e può vedere la fine del processo aspettando che layoutIfNeeded esca. E poi puoi osservare il valore risultante che ti interessa.

+1

A dire il vero, non mi aspettavo che funzionasse, ma lo è. Sto chiamando 'layoutIfNeeded' in' viewWillAppear: 'ora e come hai descritto, tutte le subviews sono state formattate correttamente in seguito. Grazie algale per la tua risposta. – MarkHim

+0

Vivo per servire. – algal