今天研究約束時,作在頁面上動態(tài)添加View時頁面不能很好的更新約束,找到了這篇文章,解決了我的大問題,在此感謝博主。
用到自動約束,就離不開一下四個方法:
@interface UIView (UIConstraintBasedLayoutCoreMethods)
- (void)updateConstraintsIfNeeded NS_AVAILABLE_IOS(6_0); // Updates the constraints from the bottom up for the view hierarchy rooted at the receiver. UIWindow's implementation creates a layout engine if necessary first.
- (void)updateConstraints NS_AVAILABLE_IOS(6_0); // Override this to adjust your special constraints during a constraints update pass
- (BOOL)needsUpdateConstraints NS_AVAILABLE_IOS(6_0);
- (void)setNeedsUpdateConstraints NS_AVAILABLE_IOS(6_0);
@end
而這四個方法,對于它們的具體的用途和調(diào)用時機理解,很長一段時間我是迷迷糊糊的。經(jīng)過一番研究,現(xiàn)在就試著把它解釋清楚?。?!
- (void)updateConstraintsIfNeeded
官網(wǎng)文檔的解釋:
Updates the constraints for the receiving view and its subviews.
Whenever a new layout pass is triggered for a view, the system invokes this method to ensure that any constraints for the view and its subviews are updated with information from the current view hierarchy and its constraints. This method is called automatically by the system, but may be invoked manually if you need to examine the most up to date constraints.
Subclasses should not override this method.
更新視圖和它的子視圖的約束。
每當(dāng)一個新的布局,通過觸發(fā)一個視圖,系統(tǒng)調(diào)用此方法以確保視圖和其子視圖的任何約束與當(dāng)前視圖層次結(jié)構(gòu)和約束信息更新。這種方法被系統(tǒng)自動調(diào)用,但如果需要檢查最新的約束條件,可以手動調(diào)用這個方法。
子類不應(yīng)重寫此方法。
注解:立即出發(fā)約束更新。
- (void)updateConstraints
官網(wǎng)文檔的解釋:
Updates constraints for the view.
Custom views that set up constraints themselves should do so by overriding this method. When your custom view notes that a change has been made to the view that invalidates one of its constraints, it should immediately remove that constraint, and then call setNeedsUpdateConstraints to note that constraints need to be updated. Before layout is performed, your implementation of updateConstraints will be invoked, allowing you to verify that all necessary constraints for your content are in place at a time when your custom view’s properties are not changing.
You must not invalidate any constraints as part of your constraint update phase. You also must not invoke a layout or drawing phase as part of constraint updating.
Important:Important
Call [super updateConstraints] as the final step in your implementation.
更新視圖的約束。
自定義視圖應(yīng)該通過重寫此方法來設(shè)置自己的約束。當(dāng)你的自定義視圖有某個約束發(fā)生了變化或失效了,應(yīng)該立即刪除這個約束,然后調(diào)用setNeedsUpdateConstraints標(biāo)記約束需要更新。系統(tǒng)在進行布局layout之前,會調(diào)用updateConstraints,讓你確認(rèn)(設(shè)置)在視圖的屬性不變時的必要約束。在更新約束階段你不應(yīng)該使任何一個約束失效,而且不能讓layerout和drawing作為更新約束的一部分。
重要提示:要在實現(xiàn)的最后調(diào)用[super updateConstraints]。
注解:自定義view應(yīng)該重寫此方法在其中建立constraints.
- (BOOL)needsUpdateConstraints
這個很簡單,返回是否需要更新約束。constraint-based layout system使用此返回值去決定是否需要調(diào)用updateConstraints作為正常布局過程的一部分。
- (void)setNeedsUpdateConstraints
官方文檔解釋:
Controls whether the view’s constraints need updating.
When a property of your custom view changes in a way that would impact constraints, you can call this method to indicate that the constraints need to be updated at some point in the future. The system will then call updateConstraints as part of its normal layout pass. Updating constraints all at once just before they are needed ensures that you don’t needlessly recalculate constraints when multiple changes are made to your view in between layout passes.
控制視圖的約束是否需要更新。
當(dāng)你的自定義視圖的屬性改變切影響到約束,你可以調(diào)用這個方法來標(biāo)記未來的某一點上需要更新的約束。然后系統(tǒng)將調(diào)用updateconstraints。
注解:這個方法和updateConstraintsIfNeeded關(guān)系有點曖昧,updateConstraintsIfNeeded是立即更新,二這個方法是標(biāo)記需要更新,然后系統(tǒng)決定更新時機。
這里再補充一下Auto layout知識
Auto layout在view顯示之前,還有兩個步驟:updating constraints 和laying out views。每一個步驟都依賴于上一個。display依賴layout,而layout依賴updating constraints。 updating constraints->layout->display
第一步:
updating constraints,被稱為測量階段,其從下向上(from subview to super view),為下一步layout準(zhǔn)備信息??梢酝ㄟ^調(diào)用方法setNeedUpdateConstraints去觸發(fā)此步。constraints的改變也會自動的觸發(fā)此步。但是,當(dāng)你自定義view的時候,如果一些改變可能會影響到布局的時候,通常需要自己去通知Auto layout,updateConstraintsIfNeeded。
自定義view的話,通??梢灾貙憉pdateConstraints方法,在其中可以添加view需要的局部的contraints。
第二步:
layout,其從上向下(from super view to subview),此步主要應(yīng)用上一步的信息去設(shè)置view的center和bounds??梢酝ㄟ^調(diào)用setNeedsLayout去觸發(fā)此步驟,此方法不會立即應(yīng)用layout。如果想要系統(tǒng)立即的更新layout,可以調(diào)用layoutIfNeeded。另外,自定義view可以重寫方法layoutSubViews來在layout的工程中得到更多的定制化效果。
第三步:
display,此步時把view渲染到屏幕上,它與你是否使用Auto layout無關(guān),其操作是從上向下(from super view to subview),通過調(diào)用setNeedsDisplay觸發(fā),
因為每一步都依賴前一步,因此一個display可能會觸發(fā)layout,當(dāng)有任何layout沒有被處理的時候,同理,layout可能會觸發(fā)updating constraints,當(dāng)constraint system更新改變的時候。
需要注意的是,這三步不是單向的,constraint-based layout是一個迭代的過程,layout過程中,可能去改變constraints,有一次觸發(fā)updating constraints,進行一輪layout過程。
注意:如果你每一次調(diào)用自定義layoutSubviews都會導(dǎo)致另一個布局傳遞,那么你將會陷入一個無限循環(huán)中。
本文轉(zhuǎn)載自http://blog.csdn.net/gang544043963/article/details/52440621
感謝博主的分享。