2015-06-23 55 views
2

製圖約束我,我想是這樣的一個觀點:與TopLayoutGuide

|---------------| 
|    | <- navBar 
|---------------| 
|    | <- topView 
|---------------| 
|    | 
|    | 
|    | 
|---------------| 

一切我想要的是堅持topView.top到navBar.bottom。我決定去與地圖製圖學與執行以下代碼(儘量堅持MVC OFC):

在我UIViewController子類:

override func viewWillLayoutSubviews() { 
    super.viewWillLayoutSubviews() 

    aView?.topLayoutGuide = self.topLayoutGuide // where aView is my subclass of UIView, inserted in loadView method 
} 

在我UIView子類:

var topLayoutGuide: UILayoutSupport? 

override func updateConstraints() { 
    var constraint = NSLayoutConstraint?() 
    layout(topView) { (topView) in 
     constraint = topView.top == topView.superview!.top 
    } 
    topView.superview!.removeConstraint(constraint!) 

    layout(topView) { topView in 
     topView.top == topView.superview!.top + (self.topLayoutGuide?.length ?? 0) 
     topView.height == 67 
     topView.left == topView.superview!.left 
     topView.width == topView.superview!.width 
    } 

    super.updateConstraints() 
} 

的問題是我收到以下日誌,我不知道如何解決它:

Unable to simultaneously satisfy constraints. 
[...] 
(
    "<NSLayoutConstraint:0x7fe6a64e4800 V:|-(64)-[UIView:0x7fe6a6505d80] (Names: '|':MyApp.MyView:0x7fe6a360d4c0)>", 
    "<NSLayoutConstraint:0x7fe6a3538a80 V:|-(0)-[UIView:0x7fe6a6505d80] (Names: '|':MyApp.MyView:0x7fe6a360d4c0)>" 
) 

似乎我需要一些幫助。如何正確地做到這一點?我不想在UIViewController中實施約束,我不想使用Storyboards

感謝您的幫助!

回答

2

一種解決方案:創建到特定NSLayoutConstraint參考,並更新其constant

var topLayoutConstraint: NSLayoutConstraint! 

override func updateConstraints() { 
    layout(topView) { topView in 
     topLayoutConstraint = topView.top == topView.superview!.top 
     topView.height == 67 
     topView.left == topView.superview!.left 
     topView.width == topView.superview!.width 
    } 

    super.updateConstraints() 
} 

......再後來,你可以調整NSLayoutConstraint的像這樣的常數:

topLayoutConstraint.constant = 50 

剩下的唯一問題是 - 你什麼時候更新topLayoutConstraint?一種解決方案是創建一個協議,MyViewInterface

protocol MyViewInterface: class { 
    var topLayoutGuideLength: CGFloat { get set } 
} 

然後,在我們的UIView,當topLayoutGuideLength性質發生變化,我們調整我們的NSLayoutConstraintconstant

public class MyView: UIView, MyViewInterface { 
    public var topLayoutGuideLength: CGFloat = 0 { 
     didSet { 
      topLayoutConstraint.constant = topLayoutGuideLength 
     } 
    } 
} 

最後,在我們的UIViewController (我們的topLayoutGuide住在哪裏):

public class myViewController: UIViewController { 

    private var myView: MyView 

    // ... 

    public override func viewDidLayoutSubviews() { 
     super.viewDidLayoutSubviews() 

     myView.topLayoutGuideLength = topLayoutGuide.length 
    } 
} 

最終結果?每當viewDidLayoutSubviews()在我們的UIViewController上被觸發時,我們的myViewtopLayoutGuideLength屬性被更新,這觸發該topLayoutConstraintconstant中的改變。

+0

我剛剛從'autolayout'辭職臨時工,目前我在'layoutSubviews'中設置了框架 - 這樣''topLayoutGuide'沒有問題。我無法測試您的解決方案,但我嘗試了一些類似的結果。我接受這個答案,因爲它可能是適當的解決方案;)。 – Vive

+1

對我有意義!我想這個問題有點陳舊,但是我昨天在處理這個相同的問題,遇到了你的問題,上面的代碼就是我用來處理它的。感謝接受! :) – bryanjclark

1

另一種缺乏從製圖文檔...

我碰到topLayoutGuideCartographybottomLayoutGuideCartography特性來作爲一個UIViewController擴展製圖。使用它們可以在不覆蓋的情況下爲您提供所需的輸出viewDidLayoutSubviews

您可以簡單地使用此屬性來錨定視圖的頂部。

override func updateConstraints() { 
    layout(topView) { topView in 
     topView.top == topLayoutGuideCartography 
     topView.height == 67 
     topView.left == topView.superview!.left 
     topView.width == topView.superview!.width 
    } 

    super.updateConstraints() 
} 
+0

它似乎是視圖控制器的屬性,我排除了作爲我的問題中的答案,我是對嗎?請把問題讀到最後。 – Vive

+0

另外,我看不到'topLayoutGuide'和'topLayoutGuideCartography'之間的區別。他們似乎是一樣的?另一件事是,我認爲你沒有必要重寫'viewDidLayoutSubviews',因爲它將值傳遞給視圖,你忽略了什麼。我希望它在視圖中,所以它是MVC或MVVM。 – Vive

+0

@Vive通常你不能將'topLayoutGuide'傳遞給'anyView.top',因爲它們不是匹配的類型。 'topLayoutGuideCartography'只是一個代理。 同時重寫'viewDidLayoutSubviews'並不是所有的時間都是必需的。這可能是因爲我寫了他們的方式。我沒有像'updateConstraints'那樣更新它們。因爲文檔本身也建議在需要時更新它們。一切都發生在我的viewDidLoad這裏。你可以看到這是一個VC案例。在查看案例中可能會有所不同。 – erenkabakci