2017-02-24 68 views
0

我正在使用Swift 3,iOS 10,XCode 8.2。Swift 3 - 以編程方式創建標題欄約束

在我的代碼中,我需要以編程方式創建一個UIViewController,因此也需要以編程方式指定其佈局和內容。

@IBAction func testViewController() { 

    let detailViewController = UIViewController() 
    detailViewController.view.backgroundColor = UIColor.white 

    let titleLabel: UILabel = { 
     let label = UILabel() 
     label.translatesAutoresizingMaskIntoConstraints = false 
     label.backgroundColor = UIColor.blue 
     label.text = "Scan Results" 
     label.textAlignment = .center 
     label.font = UIFont.boldSystemFont(ofSize: 18) 
     label.textColor = UIColor.white 
     return label 
    }() 

    let titleConstraints: [NSLayoutConstraint] = [ 
     NSLayoutConstraint(item: titleLabel, attribute: .left, relatedBy: .equal, toItem: self.view, attribute: .left, multiplier: 1, constant: 0), 
     NSLayoutConstraint(item: titleLabel, attribute: .right, relatedBy: .equal, toItem: self.view, attribute: .right, multiplier: 1, constant: 0), 
     NSLayoutConstraint(item: titleLabel, attribute: .top, relatedBy: .equal, toItem: self.view, attribute: .top, multiplier: 1, constant: 0), 
     NSLayoutConstraint(item: titleLabel, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 40) 
    ] 

    detailViewController.view.addSubview(titleLabel) 

    detailViewController.view.addConstraints(titleConstraints) 

    self.navigationController?.pushViewController(detailViewController, animated: true) 
} 

在垂直視圖(忽略所有的其他垃圾;僅僅着眼藍色標題欄上):

enter image description here

但在水平視圖:

enter image description here

什麼是正確的約束設置,以便佔用整個酒吧的寬度,並沒有多餘的空間自頂部狀態欄消失時水平?

編輯

使@thexande建議後,我得到了一個錯誤:

[LayoutConstraints] The view hierarchy is not prepared for the constraint: <NSLayoutConstraint:0x608000098100 UILabel:0x7fe35b60edc0'Scan Results'.left == UIView:0x7fe35b405c20.left (inactive)> When added to a view, the constraint's items must be descendants of that view (or the view itself). This will crash if the constraint needs to be resolved before the view hierarchy is assembled. Break on -[UIView(UIConstraintBasedLayout) _viewHierarchyUnpreparedForConstraint:] to debug. 2017-02-24 21:01:59.807 EOB-Reader[78109:10751346] * Assertion failure in -[UIView _layoutEngine_didAddLayoutConstraint:roundingAdjustment:mutuallyExclusiveConstraints:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit_Sim/UIKit-3600.6.21/NSLayoutConstraint_UIKitAdditions.m:649 2017-02-24 21:01:59.951 EOB-Reader[78109:10751346] * Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Impossible to set up layout with view hierarchy unprepared for constraint.'

我也更新了我的代碼在原崗位。

回答

4

發生這種情況的原因是因爲您正在使用框架。您根據屏幕的寬度計算了框架。你不需要框架,你可以使用自動佈局來完成這一切。相反,您應該使用約束將您的標籤固定在超級視圖邊界上,並給它一個靜態高度。例如:

lazy var titleConstraints: [NSLayoutConstraint] = [ 
    NSLayoutConstraint(item: self.titleLabel, attribute: .left, relatedBy: .equal, toItem: self.view, attribute: .left, multiplier: 1, constant: 0), 
    NSLayoutConstraint(item: self.titleLabel, attribute: .right, relatedBy: .equal, toItem: self.view, attribute: .right, multiplier: 1, constant: 0), 
    NSLayoutConstraint(item: self.titleLabel, attribute: .top, relatedBy: .equal, toItem: self.view, attribute: .top, multiplier: 1, constant: 0), 
    NSLayoutConstraint(item: self.titleLabel, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 40) 
] 

然後,在viewDidLoad中()

self.view.addConstraints(titleConstraints) 

你完全可以簡化您的標籤聲明,像這樣。不要忘了自動調整大小掩蔽標誌得到限制正常工作:

let titleLabel: UILabel = { 
    let label = UILabel() 
    label.translatesAutoresizingMaskIntoConstraints = false 
    label.backgroundColor = UIColor.blue 
    label.text = "Scan Results" 
    label.textAlignment = .center 
    label.textColor = UIColor.white 
    return label 
}() 

最後,你在做怪數學,讓您的視圖控制器的頂部緊靠您的導航欄控制器的底部。刪除所有垃圾,並把在viewDidLoad中()以下的,讓您的視圖控制器的右上方對你UINavigationBar的底部:

self.edgesForExtendedLayout = [] 

更新:

這裏的問題是要附加的意見和限制到尚未分配的視圖控制器中。

我們在viewDidLoad()中追加子視圖和約束的原因是因爲我們無法在視圖....加載到內存之前添加子視圖和約束。否則,它不在那裏,你會得到上面的錯誤。考慮打破了你的detailViewController成一個類的聲明,就像這樣:

class detailViewController: UIViewController { 
let eobTitleLabel: UILabel = { 
    let label = UILabel() 
    label.translatesAutoresizingMaskIntoConstraints = false 
    label.backgroundColor = UIColor.blue 
    label.text = "Scan Results" 
    label.textAlignment = .center 
    label.font = UIFont.boldSystemFont(ofSize: 18) 
    label.textColor = UIColor.white 
    return label 
}() 

    lazy var eobTitleConstraints: [NSLayoutConstraint] = [ 
     NSLayoutConstraint(item: self.eobTitleLabel, attribute: .left, relatedBy: .equal, toItem: self.view, attribute: .left, multiplier: 1, constant: 0), 
     NSLayoutConstraint(item: self.eobTitleLabel, attribute: .right, relatedBy: .equal, toItem: self.view, attribute: .right, multiplier: 1, constant: 0), 
     NSLayoutConstraint(item: self.eobTitleLabel, attribute: .top, relatedBy: .equal, toItem: self.view, attribute: .top, multiplier: 1, constant: 0), 
     NSLayoutConstraint(item: self.eobTitleLabel, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 40) 
    ] 

    override func viewDidLoad() { 
     self.view.addSubview(eobTitleLabel) 
     self.view.addConstraints(self.eobTitleConstraints) 
    } 
} 

而且,不脫落的進攻,但你的代碼是怎樣的一個爛攤子。在未來應該避免的事情:

  1. 將限制添加到不存在的標籤。 (重命名修復約束的標籤)
  2. 您正在使用outlet方法聲明變量。不要這樣做,在類級別聲明方法和屬性。
  3. 閱讀關於OOP以及它如何在swift中實現。這將幫助你理解的方法和模式來完成你的任務:)
+0

這是一個很大的幫助。謝謝。我提出了您的建議更改,但是我收到了一個包含在我編輯的原始文章中的錯誤。 – noblerare

+0

對不起。我把你的建議提取到一個單獨的'ViewController'類中,然後我將它實例化。感謝你的幫助! – noblerare

+0

當然!祝你好運! – thexande

相關問題