在用xib中的約束做一些動(dòng)畫時(shí),相信很多小伙伴都遇到不少坑,下面總結(jié)下最近自己遇到的一些坑,歡迎各位大神糾正以及指教:
layoutSubviews
該方法默認(rèn)沒人做任何事,需要自己重寫,有很多地方系統(tǒng)會(huì)自動(dòng)調(diào)用這個(gè)方法:
- 初始化時(shí)不會(huì)調(diào)用layoutSubviews,如果設(shè)置了非CGRectZero的frame就會(huì)調(diào)用
- 調(diào)用addSubView時(shí),系統(tǒng)會(huì)自動(dòng)調(diào)用layoutSubviews
- 當(dāng)view的frame發(fā)生變化時(shí),會(huì)調(diào)用layoutSubviews
- UIScrollView滾動(dòng)的時(shí)候回調(diào)用layoutSubviews
setNeedsLayout
標(biāo)記view需要重新布局,但是不會(huì)立刻刷新,系統(tǒng)會(huì)自動(dòng)調(diào)用layoutSubviews,然后自行調(diào)用layoutIfNedded后,立刻刷新。
layoutIfNeeded
在有需要刷新的地方調(diào)用此方法
下面是幾個(gè)例子:
- 例1:
@interface ViewController ()
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *blueViewContant;
@end
- (IBAction)btnEvent:(id)sender {
[UIView animateWithDuration:3 animations:^{
self.blueViewContant.constant = 300;
}];
}
動(dòng)畫效果:

blueTest.gif
你會(huì)發(fā)現(xiàn)并沒有什么卵用,而且制作gif的軟件也有點(diǎn)辣雞,壓根沒有這個(gè)動(dòng)畫過程,下面我試下用layoutIfNeeded方法
- 例2:
@interface ViewController ()
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *blueViewContant;
@end
- (IBAction)btnEvent:(id)sender {
[UIView animateWithDuration:3 animations:^{
self.blueViewContant.constant = 300;
[self.view layoutIfNeeded];
}];
self.yellowViewContant.constant = 300;
}

blueTest.gif
這次效果就很明顯了,就是說如果用xib中的Constraint來設(shè)置動(dòng)畫,一定要在開始動(dòng)畫的地方調(diào)用layoutIfNeeded方法,告訴系統(tǒng)這時(shí)候開始刷新
- 例3
@interface ViewController ()
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *blueViewContant;
@property (weak, nonatomic) IBOutlet NSLayoutConstraint *yellowViewContant;
@end
- (IBAction)btnEvent:(id)sender {
[UIView animateWithDuration:3 animations:^{
self.blueViewContant.constant = 300;
[self.view layoutIfNeeded];
}];
self.yellowViewContant.constant = 300;
}

blueTest.gif
總結(jié):如果想要用Constraint設(shè)置動(dòng)畫,一定要在調(diào)用layoutIfNeeded方面前設(shè)置Constraint的變化,如果不想view以動(dòng)畫的形式改變,那么久在調(diào)用layoutIfNeeded之后設(shè)置Constraint,或者不調(diào)用layoutIfNeeded.