如何在不破坏约束的情况下以编程方式将UITextField添加到UIScrollView?

时间:2017-10-19 17:00:02

标签: ios ios-autolayout

案例是这样的:我有一个嵌入UIScrollView的表单,其形式有一个用户可以添加N个textField的部分,所以如果一开始我有这个:

UITextField - textField1
UIButton - Add

按下Add时,我希望这样:

UITextField - textField1
UITextField - textField2
UIButton - Add

虽然添加了文本字段,但无法满足约束,因此UI中断

behavior

该日志:

[LayoutConstraints] 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. 
(
    "<_UILayoutSupportConstraint:0x1c4c800a0 _UILayoutGuide:0x106ccf4e0.height == 64   (active)>",
    "<_UILayoutSupportConstraint:0x1c4c80050 V:|-(0)-[_UILayoutGuide:0x106ccf4e0]   (active, names: '|':UIView:0x106ccdc10 )>",
    "<_UILayoutSupportConstraint:0x1c4c80ff0 _UILayoutGuide:0x106ccf6d0.height == 0   (active)>",
    "<_UILayoutSupportConstraint:0x1c4c801e0 _UILayoutGuide:0x106ccf6d0.bottom == UIView:0x106ccdc10.bottom   (active)>",
    "<NSLayoutConstraint:0x1c4c80550 UIImageView:0x106cce6c0.height == 5   (active)>",
    "<NSLayoutConstraint:0x1c4c80640 UILabel:0x106ccf070'Completa tu Perfil'.height == 24   (active)>",
    "<NSLayoutConstraint:0x1c0c886b0 form-view.height == 579   (active, names: form-view:0x10ed307c0 )>",
    "<NSLayoutConstraint:0x1c0c8a1e0 V:|-(0)-[form-view]   (active, names: form-view:0x10ed307c0, '|':UIScrollView:0x107a37000 )>",
    "<NSLayoutConstraint:0x1c0c8a320 V:[form-view]-(0)-[profiles-view]   (active, names: profiles-view:0x106ccd430, form-view:0x10ed307c0 )>",
    "<NSLayoutConstraint:0x1c4c80af0 V:[_UILayoutGuide:0x106ccf4e0]-(10)-[UILabel:0x106ccf070'Completa tu Perfil']   (active)>",
    "<NSLayoutConstraint:0x1c4c80cd0 V:[UILabel:0x106ccf070'Completa tu Perfil']-(8)-[UIImageView:0x106cce6c0]   (active)>",
    "<NSLayoutConstraint:0x1c4c80d20 V:[UIImageView:0x106cce6c0]-(0)-[UIScrollView:0x107a37000]   (active)>",
    "<NSLayoutConstraint:0x1c4c80e10 UIImageView:0x106ccddf0.top == profiles-view.top   (active, names: profiles-view:0x106ccd430 )>",
    "<NSLayoutConstraint:0x1c4c80f00 V:[UIImageView:0x106ccddf0]-(0)-[_UILayoutGuide:0x106ccf6d0]   (active)>",
    "<NSLayoutConstraint:0x1c0c8bdb0 'UIView-Encapsulated-Layout-Height' UIView:0x106ccdc10.height == 667   (active)>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x1c0c886b0 form-view.height == 579   (active, names: form-view:0x10ed307c0 )>

因此,由于高度约束被破坏,AutoLayout会按照边距限制排列元素,这样可以使视图破坏。

话虽这么说,我添加约束的方式是:

func addModelButtonAction(_ sender: Any) { // an IBAction 
    addButton.isHighlighted = false
    let last = modelTextFields.last!
    let textField = last.createCopy() // extension method for creating a copy of the last textField
    modelTextFieldsView.insertSubview(textField, belowSubview: last)
    let growth = last.frame.height + 8 // the 8 represents the top spacing between textFields
    formViewHeight.constant += growth // increasing height of the view where the form is embeded
    modelTextFieldsHeight.constant += growth // increasing height of the view where the textFields are embeded
    UIView.animate(withDuration: 0.5) {
        self.view.layoutIfNeeded()
        textField.frame.origin.y += growth // moving new textField below the previous one
    }

    modelTextFields.append(textField) // array of UITextField to keep track of the textFields in screen
}

视图的对齐矩形: view-rectangles

视图的层次结构:

view-hierarchy

如何使这项工作符合预期呢?我很感谢你的帮助,因为我一直试图弄清楚这一点,但没有任何成功。

提前致谢!

1 个答案:

答案 0 :(得分:2)

您有几种方法可以解决此布局问题:

就个人而言,我可能会尝试在UIStackView中嵌入这些视图。堆栈视图将用于管理垂直布局,允许您根据需要插入和删除子视图。如果您使用Storyboard,UIStackView在Interface Builder中特别容易使用。

或者,您可以使用UITableView进行此布局;虽然您需要自己管理数据源和单元格,但它会代表您管理垂直流程,从而抽象出大部分布局问题。

你可以通过仔细管理不同约束的优先级来使这个布局无法工作,允许一些在布局改变时被破坏,但这可能是一项单调乏味的工作。