Me gustaría agregar la respuesta de n8gray que en algunos casos necesitará llamar setNeedsLayout
seguido 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 contentView
propiedad y una edgeInsets
propiedad que permite establecer los márgenes alrededor de contentView. layoutSubviews
se 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 edgeInsets
propiedad, debe anular el establecedor de la edgeInsets
siguiente manera y llamar setNeedsLayout
seguido 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.