Saya ingin menambahkan jawaban n8gray bahwa dalam beberapa kasus Anda perlu menelepon setNeedsLayout
diikuti oleh layoutIfNeeded
.
Misalnya, Anda menulis tampilan kustom yang memperluas UIView, di mana pemosisian subview rumit dan tidak dapat dilakukan dengan AutoresizingMask atau iOS6 AutoLayout. Penentuan posisi kustom dapat dilakukan dengan mengganti layoutSubviews
.
Sebagai contoh, katakanlah Anda memiliki tampilan kustom yang memiliki contentView
properti dan edgeInsets
properti yang memungkinkan untuk menyetel margin di sekitar contentView. layoutSubviews
akan terlihat seperti ini:
- (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);
}
Jika Anda ingin dapat menganimasikan perubahan bingkai setiap kali Anda mengubah edgeInsets
properti, Anda perlu mengganti edgeInsets
penyetel sebagai berikut dan memanggil setNeedsLayout
diikuti oleh 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
}
Dengan demikian, jika Anda melakukan hal berikut, jika Anda mengubah properti edgeInsets di dalam blok animasi, perubahan bingkai dari contentView akan dianimasikan.
[UIView animateWithDuration:2 animations:^{
customView.edgeInsets = UIEdgeInsetsMake(45, 17, 18, 34);
}];
Jika Anda tidak menambahkan panggilan ke layoutIfNeeded dalam metode setEdgeInsets, animasi tidak akan berfungsi karena layoutSubviews akan dipanggil pada siklus pembaruan berikutnya, yang sama dengan memanggilnya di luar blok animasi.
Jika Anda hanya memanggil layoutIfNeeded dalam metode setEdgeInsets, tidak akan ada yang terjadi karena tanda setNeedsLayout tidak disetel.