在 Swift 中对 UIButton 设置自动布局约束
Setting Autolayout Constraints on UIButton in Swift
我仍在尝试了解 Swift Autolayouts XCode 6.3。我已经设置了一个视图控制器,我在 Interface Builder 中贴了几个标签。我已经以编程方式添加了一个 UITextView 和 UIImageView,并且正在尝试在屏幕底部添加一个 UIButton 并以编程方式设置其约束。但是,当视图尝试加载时,我不断收到错误消息。
在class定义下:
let infoButton = UIButton.buttonWithType(UIButtonType.System) as! UIButton
var descView: UITextView!
var picView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
infoButton.setTranslatesAutoresizingMaskIntoConstraints(false)
infoButton.setTitle("Information",forState:UIControlState.Normal)
self.view.addSubview(infoButton)
self.descView = UITextView(frame:CGRectMake(0,0,300,290))
self.descView.selectable = false
self.userInteractionEnabled = false
self.descView.text = "testing block of text"
self.container.frame = CGRect(x:20,y:160,width:300,height:290)
self.picView = UIImageView(image:"house.png")
self.view.addSubview(container)
self.container.addSubview(picView)
//setup button constraints
let viewsDictionary = ["infoButton":infoButton]
let button_constraint_H:Array = NSLayoutConstraint.constraintsWithVisualFormat("H:|-[infoButton]-|", options:NSLayoutFormatOptions(0),metrics:nil,views:viewsDictionary)
let button_constraint_V:Array = NSLayoutConstraint.constraintsWithVisualFormat("V:[infoButton]-0-|",options:NSLayoutFormatOptions(0),metrics:nil, views:viewsDictionary)
infoButton.addConstraints(button_constraint_H)
infoButton.addConstraints(button_constraint_V)
}
应用程序在 viewDidLoad() 方法中崩溃。
2015-06-17 16:59:14.902 LayoutTest[20323:5937743] The view hierarchy is not prepared for the constraint: <NSLayoutConstraint:0x7fc5b9de4140 UIButton:0x7fc5b9ec3e40'Information'.leading == UIView:0x7fc5b9eaf860.leadingMargin>
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 _viewHierarchyUnpreparedForConstraint:] to debug.
2015-06-17 16:59:14.904 LayoutTest[20323:5937743] View hierarchy unprepared for constraint.
Constraint: <NSLayoutConstraint:0x7fc5b9de4140 UIButton:0x7fc5b9ec3e40'Information'.leading == UIView:0x7fc5b9eaf860.leadingMargin>
Container hierarchy:
<UIButton: 0x7fc5b9ec3e40; frame = (0 0; 0 0); opaque = NO; layer = <CALayer: 0x7fc5b9ee2a80>>
View not found in container hierarchy: <UIView: 0x7fc5b9eaf860; frame = (0 0; 375 667); autoresize = W+H; layer = <CALayer: 0x7fc5b9ed9c70>>
That view's superview: NO SUPERVIEW
2015-06-17 16:59:14.925 LayoutTest[20323:5937743] *** Terminating app due to uncaught exception 'NSGenericException', reason: 'Unable to install constraint on view. Does the constraint reference something from outside the subtree of the view? That's illegal. constraint:<NSLayoutConstraint:0x7fc5b9de4140 UIButton:0x7fc5b9ec3e40'Information'.leading == UIView:0x7fc5b9eaf860.leadingMargin> view:<UIButton: 0x7fc5b9ec3e40; frame = (0 0; 0 0); opaque = NO; layer = <CALayer: 0x7fc5b9ee2a80>>'
我到底做错了什么?
我已经使用 Interface Builder 为其他项目(标签)定义了一些约束,但需要能够定义按钮等,并通过代码为同一视图设置约束。
这是我与 Swift 在一起的第一周,所以请保持温柔!
晋
所以我认为您只是为按钮设置约束,但自动布局需要对视图层次结构中的所有元素都有约束。
您将按钮和容器添加到超级视图中,但没有说明它们之间的关系,我认为您只需要更多约束。
我建议尝试使用故事板,因为我发现它更清楚视图和约束之间的关系。
总之,祝你好运。
您看到的特定崩溃是因为您将约束添加到按钮,而不是它的父视图。约束与 self.view
和 infoButton
相关,因此应添加到 self.view
。如果约束仅与按钮相关,即它通过与另一个视图无关的显式值定义按钮高度,则可以将其添加到按钮。您也不能轻易地在同一个视图中混合设置框架和约束,您最终可能会得到意想不到的视图布局。 descView
、container
和 picView
都需要通过约束来定义,而不是手动设置框架。
换行
infoButton.addConstraints(button_constraint_H)
infoButton.addConstraints(button_constraint_V)
到
self.view.addConstraints(button_constraint_H)
self.view.addConstraints(button_constraint_V)
您的自动版式代码存在一些问题,其中一些非常基础。 Autolayout 会花费您一些时间来理解,有时这很古怪。彻底阅读它会让你真正受益。潜入并尝试解决问题会让您陷入一些非常令人沮丧的境地。我建议阅读 Apple 的这份指南:
阅读本书前4-5章:
https://itunes.apple.com/gb/book/ios-auto-layout-demystified/id727646366?mt=11
并在此处遵循一些示例:
http://www.raywenderlich.com/50317/beginning-auto-layout-tutorial-in-ios-7-part-1
试试这个代码
self.view.addConstraint(NSLayoutConstraint(item: infoButton, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.Leading, multiplier: 1.0, constant: 0.0))
self.view.addConstraint(NSLayoutConstraint(item: infoButton, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal, toItem: self, attribute: NSLayoutAttribute.Trailing, multiplier: 1.0, constant: 0.0))
self.view.addConstraint(NSLayoutConstraint(item: infoButton, attribute: NSLayoutAttribute.Bottom, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.Bottom, multiplier: 1.0, constant: 0.0))
这个方法最终对我有用,上面的方法对我不起作用应用程序在 Xcode 13.3 时一直崩溃。
我通过创建按钮并使用 x 和 y 位置以及使用 UIScreen class 获取设备屏幕宽度和高度来计算距离来解决问题。
例如:
让按钮:UIButton = UIButton(frame: CGRect(x: (UIScreen.main.bounds.width - ( 7 * 30)) / 2, y: UIScreen.main.bounds.height * 0.90, width: 200, height: 50))
[
我仍在尝试了解 Swift Autolayouts XCode 6.3。我已经设置了一个视图控制器,我在 Interface Builder 中贴了几个标签。我已经以编程方式添加了一个 UITextView 和 UIImageView,并且正在尝试在屏幕底部添加一个 UIButton 并以编程方式设置其约束。但是,当视图尝试加载时,我不断收到错误消息。
在class定义下:
let infoButton = UIButton.buttonWithType(UIButtonType.System) as! UIButton
var descView: UITextView!
var picView: UIImageView!
override func viewDidLoad() {
super.viewDidLoad()
infoButton.setTranslatesAutoresizingMaskIntoConstraints(false)
infoButton.setTitle("Information",forState:UIControlState.Normal)
self.view.addSubview(infoButton)
self.descView = UITextView(frame:CGRectMake(0,0,300,290))
self.descView.selectable = false
self.userInteractionEnabled = false
self.descView.text = "testing block of text"
self.container.frame = CGRect(x:20,y:160,width:300,height:290)
self.picView = UIImageView(image:"house.png")
self.view.addSubview(container)
self.container.addSubview(picView)
//setup button constraints
let viewsDictionary = ["infoButton":infoButton]
let button_constraint_H:Array = NSLayoutConstraint.constraintsWithVisualFormat("H:|-[infoButton]-|", options:NSLayoutFormatOptions(0),metrics:nil,views:viewsDictionary)
let button_constraint_V:Array = NSLayoutConstraint.constraintsWithVisualFormat("V:[infoButton]-0-|",options:NSLayoutFormatOptions(0),metrics:nil, views:viewsDictionary)
infoButton.addConstraints(button_constraint_H)
infoButton.addConstraints(button_constraint_V)
}
应用程序在 viewDidLoad() 方法中崩溃。
2015-06-17 16:59:14.902 LayoutTest[20323:5937743] The view hierarchy is not prepared for the constraint: <NSLayoutConstraint:0x7fc5b9de4140 UIButton:0x7fc5b9ec3e40'Information'.leading == UIView:0x7fc5b9eaf860.leadingMargin>
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 _viewHierarchyUnpreparedForConstraint:] to debug.
2015-06-17 16:59:14.904 LayoutTest[20323:5937743] View hierarchy unprepared for constraint.
Constraint: <NSLayoutConstraint:0x7fc5b9de4140 UIButton:0x7fc5b9ec3e40'Information'.leading == UIView:0x7fc5b9eaf860.leadingMargin>
Container hierarchy:
<UIButton: 0x7fc5b9ec3e40; frame = (0 0; 0 0); opaque = NO; layer = <CALayer: 0x7fc5b9ee2a80>>
View not found in container hierarchy: <UIView: 0x7fc5b9eaf860; frame = (0 0; 375 667); autoresize = W+H; layer = <CALayer: 0x7fc5b9ed9c70>>
That view's superview: NO SUPERVIEW
2015-06-17 16:59:14.925 LayoutTest[20323:5937743] *** Terminating app due to uncaught exception 'NSGenericException', reason: 'Unable to install constraint on view. Does the constraint reference something from outside the subtree of the view? That's illegal. constraint:<NSLayoutConstraint:0x7fc5b9de4140 UIButton:0x7fc5b9ec3e40'Information'.leading == UIView:0x7fc5b9eaf860.leadingMargin> view:<UIButton: 0x7fc5b9ec3e40; frame = (0 0; 0 0); opaque = NO; layer = <CALayer: 0x7fc5b9ee2a80>>'
我到底做错了什么?
我已经使用 Interface Builder 为其他项目(标签)定义了一些约束,但需要能够定义按钮等,并通过代码为同一视图设置约束。
这是我与 Swift 在一起的第一周,所以请保持温柔! 晋
所以我认为您只是为按钮设置约束,但自动布局需要对视图层次结构中的所有元素都有约束。
您将按钮和容器添加到超级视图中,但没有说明它们之间的关系,我认为您只需要更多约束。
我建议尝试使用故事板,因为我发现它更清楚视图和约束之间的关系。
总之,祝你好运。
您看到的特定崩溃是因为您将约束添加到按钮,而不是它的父视图。约束与 self.view
和 infoButton
相关,因此应添加到 self.view
。如果约束仅与按钮相关,即它通过与另一个视图无关的显式值定义按钮高度,则可以将其添加到按钮。您也不能轻易地在同一个视图中混合设置框架和约束,您最终可能会得到意想不到的视图布局。 descView
、container
和 picView
都需要通过约束来定义,而不是手动设置框架。
换行
infoButton.addConstraints(button_constraint_H)
infoButton.addConstraints(button_constraint_V)
到
self.view.addConstraints(button_constraint_H)
self.view.addConstraints(button_constraint_V)
您的自动版式代码存在一些问题,其中一些非常基础。 Autolayout 会花费您一些时间来理解,有时这很古怪。彻底阅读它会让你真正受益。潜入并尝试解决问题会让您陷入一些非常令人沮丧的境地。我建议阅读 Apple 的这份指南:
阅读本书前4-5章:
https://itunes.apple.com/gb/book/ios-auto-layout-demystified/id727646366?mt=11
并在此处遵循一些示例:
http://www.raywenderlich.com/50317/beginning-auto-layout-tutorial-in-ios-7-part-1
试试这个代码
self.view.addConstraint(NSLayoutConstraint(item: infoButton, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.Leading, multiplier: 1.0, constant: 0.0))
self.view.addConstraint(NSLayoutConstraint(item: infoButton, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal, toItem: self, attribute: NSLayoutAttribute.Trailing, multiplier: 1.0, constant: 0.0))
self.view.addConstraint(NSLayoutConstraint(item: infoButton, attribute: NSLayoutAttribute.Bottom, relatedBy: NSLayoutRelation.Equal, toItem: self.view, attribute: NSLayoutAttribute.Bottom, multiplier: 1.0, constant: 0.0))
这个方法最终对我有用,上面的方法对我不起作用应用程序在 Xcode 13.3 时一直崩溃。
我通过创建按钮并使用 x 和 y 位置以及使用 UIScreen class 获取设备屏幕宽度和高度来计算距离来解决问题。
例如:
让按钮:UIButton = UIButton(frame: CGRect(x: (UIScreen.main.bounds.width - ( 7 * 30)) / 2, y: UIScreen.main.bounds.height * 0.90, width: 200, height: 50))
[