Vorrei aggiungere la risposta di n8gray che in alcuni casi dovrai chiamare setNeedsLayoutseguito da layoutIfNeeded.
Supponiamo ad esempio che tu abbia scritto una visualizzazione personalizzata che estende UIView, in cui il posizionamento delle sottoview è complesso e non può essere eseguito con autoresizeMask o iOS6 AutoLayout. Il posizionamento personalizzato può essere eseguito sovrascrivendo layoutSubviews.
Ad esempio, supponiamo di avere una visualizzazione personalizzata che ha una contentViewproprietà e una edgeInsetsproprietà che consente di impostare i margini attorno a contentView. layoutSubviewssarebbe simile a questo:
- (void) layoutSubviews {
self.contentView.frame = CGRectMake(
self.bounds.origin.x + self.edgeInsets.left,
self.bounds.origin.y + self.edgeInsets.top,
self.bounds.size.width - self.edgeInsets.left - self.edgeInsets.right,
self.bounds.size.height - self.edgeInsets.top - self.edgeInsets.bottom);
}
Se vuoi essere in grado di animare il cambio di frame ogni volta che cambi la edgeInsetsproprietà, devi sovrascrivere il edgeInsetssetter come segue e chiamare setNeedsLayoutseguito da layoutIfNeeded:
- (void) setEdgeInsets:(UIEdgeInsets)edgeInsets {
_edgeInsets = edgeInsets;
[self setNeedsLayout]; //Indicates that the view needs to be laid out
//at next update or at next call of layoutIfNeeded,
//whichever comes first
[self layoutIfNeeded]; //Calls layoutSubviews if flag is set
}
In questo modo, se si esegue quanto segue, se si modifica la proprietà edgeInsets all'interno di un blocco di animazione, il cambio di frame di contentView verrà animato.
[UIView animateWithDuration:2 animations:^{
customView.edgeInsets = UIEdgeInsetsMake(45, 17, 18, 34);
}];
Se non aggiungi la chiamata a layoutIfNeeded nel metodo setEdgeInsets, l'animazione non funzionerà perché layoutSubviews verrà chiamato al successivo ciclo di aggiornamento, il che equivale a chiamarlo al di fuori del blocco dell'animazione.
Se chiami solo layoutIfNeeded nel metodo setEdgeInsets, non accadrà nulla poiché il flag setNeedsLayout non è impostato.