使用swift iOS8通过代码将约束设置到Storyboard中的元素

Posted

技术标签:

【中文标题】使用swift iOS8通过代码将约束设置到Storyboard中的元素【英文标题】:Set constraints through code to an element from Storyboard with swift iOS8 【发布时间】:2015-05-01 16:50:15 【问题描述】:

我有一个带有 tableView 的 ViewController。我已经在情节提要中设置了它。有没有办法以编程方式设置 tableView 的约束?我试图在 ViewController 中从我的 tableView 设置一个 IBOutlet 并为其添加约束。但这没有用。

这是我的视图控制器

import UIKit

class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate 

@IBOutlet weak var tableView: UITableView!

override func viewDidLoad() 
    super.viewDidLoad()

    addTableViewConstraints()


override func didReceiveMemoryWarning() 
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.


func addTableViewConstraints() 

    tableView.setTranslatesAutoresizingMaskIntoConstraints(false)

    var topConstraint = NSLayoutConstraint(item: self.tableView, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.Top, multiplier: 1.0, constant: 20)
    var leadingContraint = NSLayoutConstraint(item: self.tableView, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.Leading, multiplier: 1.0, constant: 0)
    var trailingConstraint = NSLayoutConstraint(item: self.tableView, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.Trailing, multiplier: 1.0, constant: 0)
    var bottomConstraint = NSLayoutConstraint(item: self.tableView, attribute: NSLayoutAttribute.Bottom, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.Bottom, multiplier: 1.0, constant: 0)

    self.view.addConstraints([topConstraint, leadingContraint, trailingConstraint, bottomConstraint])



func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
    return 5


func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell 
    var cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! UITableViewCell
    cell.textLabel?.text = "Cell"
    return cell


或者我是否也必须通过代码制作我的 tableView?

谢谢!

【问题讨论】:

你为什么要在代码中而不是在情节提要中这样做?只是好奇。 您的代码没有有什么作用? @keithbhunter 我必须在单击按钮时更改约束。如果我在情节提要中做约束,我不知道该怎么做。 @DreamingInBinary 它在控制台中抛出一条错误消息:无法同时满足约束。 按下按钮时约束会如何变化? 【参考方案1】:

您在其中一个 cmets 中提到您希望在用户按下按钮时更改约束。您可以通过为约束创建一个出口,以更少的代码实现这一点。在文档大纲页面中找到约束,然后 CTRL + 拖动到您的类以创建约束的出口。然后您可以更轻松地更改代码中的常量。

@IBOutlet weak var topConstraint: NSLayoutConstraint!
@IBOutlet weak var bottomConstraint: NSLayoutConstraint!

func buttonPressed() 
    if (/* some condition */) 
        self.topConstraint.constant += 8
        self.bottomConstraint.constant += 8
     else 
        // Return the constraints to normal, or whatever you want to do
    

【讨论】:

这也是我要做的。如果可能的话,使用 Storyboard 来做所有的约束,甚至可以为一些做占位符,就像这里的情况一样。通过这种方式,您可以利用 Storyboard 来检查所有约束。这是一种比使用代码更好的“试错”方式。【参考方案2】:

按以下方式更改您的方法addTableViewConstraints

func addTableViewConstraints() 

   tableView.setTranslatesAutoresizingMaskIntoConstraints(false)

   var topConstraint = NSLayoutConstraint(item: self.tableView, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.Top, multiplier: 1.0, constant: 20)
   var leadingContraint = NSLayoutConstraint(item: self.tableView, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.Leading, multiplier: 1.0, constant: 0)
   var trailingConstraint = NSLayoutConstraint(item: self.tableView, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.Trailing, multiplier: 1.0, constant: 0)
   var bottomConstraint = NSLayoutConstraint(item: self.tableView, attribute: NSLayoutAttribute.Bottom, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.Bottom, multiplier: 1.0, constant: 0)

   NSLayoutConstraint.activateConstraints([topConstraint, leadingContraint, trailingConstraint, bottomConstraint])

更新:

您遇到的NSIBPrototypingLayoutConstraint 约束(并导致异常)由 Interface Builder 自动生成,以使您的 Storyboard 或 XIB 视图布局明确。这样做很偷偷摸摸,但它会自动添加所需的最小约束,以便完全指定每个模棱两可的视图的位置和大小。

解决此问题的方法是在 Interface Builder 中添加所需的最小约束,以便完全指定每个视图的位置和大小,然后选择每个不需要的约束,转到右侧边栏的属性检查器,然后选中该框占位符 - 构建时移除旁边。

我通过以下方式解决了这个问题:

    打开您正在处理的 Storyboard 视图控制器。 选择您的UITableView。 选择视图控制器并从菜单中选择Editor > Resolve Auto Layout Issues > Selected View in [ ] View Controller > Add Missing Constraints

    从表视图中选择所有约束:

    从右窗格中选中以下复选框:Placeholder - Remove at build time

现在您可以在代码中手动添加所有自动布局约束,而不会出现任何警告。

希望对你有所帮助。

【讨论】:

我已经尝试了你的答案,但我仍然在控制台中收到一条错误消息“无法同时满足约束。” 这不是错误消息。这是一条警告信息。 @CeceXX 哦,对不起。但看起来 tableView 没有任何约束,因为它看起来不是预期的方式。我已经尝试以编程方式设置 tableView,并且效果很好。我想不可能在情节提要中设置 tableView 并通过代码设置 tableView 的约束。还是我错了?【参考方案3】:

假设您有一个名为myButton 的按钮,并且您想通过代码创建它的Bottom Space 约束。该约束的constant 将设置为500

这是 NSLayoutConstraint 在 Swift 中的样子。确保将此代码包含在函数中。

    var constraintButton = NSLayoutConstraint (item: myButton,
        attribute: NSLayoutAttribute.Bottom,
        relatedBy: NSLayoutRelation.Equal,
        toItem: self.view,
        attribute: NSLayoutAttribute.Bottom,
        multiplier: 1,
        constant: 500)

    // Add the constraint to the view
    self.view.addConstraint(constraintButton)

【讨论】:

以上是关于使用swift iOS8通过代码将约束设置到Storyboard中的元素的主要内容,如果未能解决你的问题,请参考以下文章

XCode 6.4 中 iOS8 Storyboard 中缺少约束图标,适用于最初在早期版本的 iOS 下编写的应用程序

Swift/iOS8:只允许某些键盘

Swift 3 iOS 兼容性

如何使用自动布局在 Swift 中为可重用的 UIView 设置约束?

在iOS8中使用Swift更改特定ViewControllers的状态栏颜色

Swift:ScrollView 不滚动(如何设置约束)?