Me gustaría agregar la respuesta de n8gray que en algunos casos necesitará llamar setNeedsLayoutseguido de layoutIfNeeded.
Digamos, por ejemplo, que escribió una vista personalizada ampliando UIView, en la que el posicionamiento de las subvistas es complejo y no se puede hacer con autoresizingMask o AutoLayout de iOS6. El posicionamiento personalizado se puede realizar anulando layoutSubviews.
Como ejemplo, digamos que tiene una vista personalizada que tiene una contentViewpropiedad y una edgeInsetspropiedad que permite establecer los márgenes alrededor de contentView. layoutSubviewsse vería así:
- (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);
}
Si desea poder animar el cambio de marco siempre que cambie la edgeInsetspropiedad, debe anular el establecedor de la edgeInsetssiguiente manera y llamar setNeedsLayoutseguido de 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
}
De esa manera, si hace lo siguiente, si cambia la propiedad edgeInsets dentro de un bloque de animación, se animará el cambio de fotograma de contentView.
[UIView animateWithDuration:2 animations:^{
customView.edgeInsets = UIEdgeInsetsMake(45, 17, 18, 34);
}];
Si no agrega la llamada a layoutIfNeeded en el método setEdgeInsets, la animación no funcionará porque se llamará a layoutSubviews en el próximo ciclo de actualización, lo que equivale a llamarlo fuera del bloque de animación.
Si solo llama a layoutIfNeeded en el método setEdgeInsets, no sucederá nada ya que la marca setNeedsLayout no está establecida.