2015-06-21 135 views
24

我有一個Autolayout和Size Classes的故事板。相當複雜的佈局,不幸的是,我不能真正確定如何在新項目中重現問題。
但是所討論的視圖被固定在屏幕的左和右邊緣與具有750的優先級的約束(即|-([email protected])-[myView]-([email protected])-|,另外它具有大於或小於1000的優先級(即|-(>=0)-[myView]-(>=0)-|)約束等於。這是爲了限制iPad的寬度,所以在容器約束中存在寬度約束width <= 600 @1000中心水平,並且視圖的寬高比約束爲3:1。說,很複雜什麼是_UITemporaryLayoutWidth,它爲什麼打破我的約束?

Interface Builder不顯示任何約束的問題。Xcode佈局預覽呈現正確的所有設備。

當我運行應用程序iOS告訴我它有衝突的約束。

Unable to simultaneously satisfy constraints. 
    Probably at least one of the constraints in the following list is one you don't want. Try this: (1) look at each constraint and try to figure out which you don't expect; (2) find the code that added the unwanted constraint or constraints and fix it. (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) 
(
    "<NSLayoutConstraint:0x7fd72853ff80 DMXKit.DipSwitchAssembly:0x7fd72990d0e0.width == 3*DMXKit.DipSwitchAssembly:0x7fd72990d0e0.height>", 
    "<NSLayoutConstraint:0x7fd728574e50 '_UITemporaryLayoutWidth' H:[DMXKit.DipSwitchAssembly:0x7fd72990d0e0(400)]>", 
    "<NSLayoutConstraint:0x7fd72856e9c0 V:[DMXKit.DipSwitchAssembly:0x7fd72990d0e0(133)]>" 
) 

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x7ffb19798000 DMXKit.DipSwitchAssembly:0x7ffb1979a000.width == 3*DMXKit.DipSwitchAssembly:0x7ffb1979a000.height> 

這重複了幾次,具有完全相同的(即相同的指針)約束。這也很奇怪,看起來約束並沒有被打破。運行時,該應用程序看起來100%正確。當我在Xcode視圖調試器中查看應用程序時,地址爲0x7ffb19798000的約束仍然存在,因此它從未被破壞。

_UITemporaryLayoutWidth constaint來自哪裏?很明顯,我沒有添加它。谷歌不會吐出有關_UITemporaryLayoutWidth的任何有用信息。有沒有人遇到過這樣的問題?

+0

我有很多的這些警告也在日誌中。雖然,它似乎沒有打破我的佈局。我想知道這些'_UITemporaryLayoutWidth來自哪裏。 – dergab

回答

0

問題的根源在於3:1的寬高比。如果我將其更改爲其他方法,那麼我現在使用4:1.4,它可以工作。我不知道爲什麼,但它有效。

我對自動佈局的內部瞭解不多,但我認爲問題在於佈局引擎如何實現約束。大小類可能是添加臨時寬度約束的原因。

不可滿足的約束似乎不是一個真正的問題,因爲它看起來像只是暫時不令人滿意。這只是在每次創建視圖時出現幾行日誌。

44

所以,我不確定這是否可以幫助你解決問題,因爲它聽起來像是在IB中構建你的佈局,但是這裏有一個問題,我剛纔遇到的問題可能會幫助其他人搜索「_UITemporaryLayoutWidth 」。

我的方案是我在init中添加了自動佈局約束,並在將視圖添加到視圖層次結構(修改按鈕邊緣插圖觸發器佈局)之前意外觸發了'layoutIfNeeded'。看起來系統添加了這些臨時約束,並且(我假設?)在視圖添加到層​​次結構後將其刪除。如果你在你的佈局中設置了特定的約束常量值(例如,你希望在這些按鈕之間有16像素,但是在這個維度上有0個空間......),那麼臨時約束會設置0維(在我的情況下),這可能會失敗。

更新:調查了一下,發現臨時約束似乎與您用來初始化父視圖的框架相對應。在我的情況下,我使用的框架是大小0x0,所以臨時約束評估相對於0x0大小,從而失敗。驗證,如果我初始化一個5x5幀,然後我看到與_UITemporaryLayoutWidth(5)約束相同的錯誤。我注意到的另一件事是,約束似乎在佈局評估過程中被添加和刪除 - 如果在我觸發佈局和分析約束之前斷開,我沒有看到臨時約束。我也沒有看到錯誤後的約束,所以我懷疑他們綜合了臨時約束,添加它們,解決然後刪除它們。

更新2:好吧,也許這是TMI,但這可能對某人有用。我目前的想法是,這些臨時約束是對系統在單個視圖層次結構中如何處理混合幀操作和自動佈局的窺視。就我而言,我的觀點沒有父母,也沒有限定其大小的限制,但它確實有一個零框架,這意味着系統假定它是解決佈局時應該使用的大小。我的想法是,系統綜合了這些視圖的臨時約束,這些視圖的框架明確地設置爲在系統遍歷層次結構時解決系統的其餘部分。

更新3:所以,我再次遇到這個問題,並希望分享一些信息。我的場景是,我試圖基本測量沒有使用systemLayoutSizeFittingSize:方法的父視圖。長話短說,在測量之前,我必須在視圖上調用layoutIfNeeded - 這是我遇到與臨時約束衝突的地方,因爲視圖沒有超視圖。臨時約束常量(維度)確實對應於在沒有超視圖的情況下在視圖上設置的任何框架 - 我認爲這是有意義的(儘管如此,在視圖上設置一個框架,您將與AutoLayout一起使用看起來很奇怪。 )我能夠解決臨時約束問題 - 說如果視圖沒有超級視圖然後將其添加到臨時超級視圖;測量;將其從臨時超級視圖中移除。希望這是有用的。

+12

...「在將視圖添加到視圖層次結構之前意外觸發'layoutIfNeeded'」 - 謝謝。 – Adama

+0

旅行者,你所尋求的答案在上面的評論中由Adama總結。 – Jano

+0

當一個視圖還沒有超級視圖時,發生在我身上,但子視圖使用AutoLayout會有一個複雜的佈局。 – DevAndArtist

6

我我的情況下,問題是以下幾點:

我創建了一個UIButton
我設置了它的寬度和高度約束。
我將按鈕添加到其超級視圖。
我將其領先和頂部佈局約束設置爲超視圖。

這產生了錯誤「Unable to simultaneously satisfy constraints」,其中一個衝突約束是_UITemporaryLayoutHeight

當我將該按鈕添加到它的超級視圖之前,在之前設置其寬度和高度約束,錯誤消失了。

6

如上所述,臨時約束似乎設置在沒有父視圖的視圖上。我發現確保translatesAutoresizingMaskIntoConstraintsfalse在頂層視圖中刪除了臨時約束。作爲:

topView.translatesAutoresizingMaskIntoConstraints = false 
0

只是一個快速補充上述評論,簡單的解決方案,我的工作是改變我的約束被創建的順序。我以編程方式在視圖和超級視圖上創建約束 - 但我在超級視圖之前完成視圖。所以我交換了它,以便superview約束先行,然後子視圖添加了它們的約束,這意味着不再需要調用_UITemporaryLayoutWidth,所以約束問題就消失了。

0

在我的情況,我只有在這種情況下,這個UITemporaryLayoutWidth衝突 1我與[UIView的新]一個觀點,我並沒有把它添加到任何上海華 2然後創建一個寬度約束這種觀點只是創建 3調用layoutIfNeeded這種觀點立即和衝突發生

所以要消除這種錯誤的方法很簡單:不要叫layoutIfNeeded它自前加入一些上海華