以编程方式添加约束时无法找到superview?

时间:2017-02-12 11:08:28

标签: ios swift autolayout

在尝试以编程方式添加约束时,请参阅此问题Making a custom UIView subview that fills its superview

我正在使用下面的代码来编程地添加两个约束;但是,我收到一条错误,指出“无法解析约束格式”,因为相关视图没有超视图。

private func setupDownView(view: UIView) {
    let downView = try? DownView(frame: view.bounds, markdownString: "")
    downView!.translatesAutoresizingMaskIntoConstraints = false
    let viewsDict = ["view": downView!]
    downView!.addConstraint(NSLayoutConstraint.constraints(
        withVisualFormat: "V:|-0-[view]-0-|",
        options: [],
        metrics: nil,
        views: viewsDict)[0])
    downView!.addConstraint(NSLayoutConstraint.constraints(
        withVisualFormat: "H:|-0-[view]-0-|",
        options: [],
        metrics: nil,
        views: viewsDict)[0])
    view.addSubview(downView!);
}

enter image description here

view auto添加到子视图后,它是否会成为超级视图?

我尝试在addSubview之前addConstraint设置约束之前添加视图,我收到错误“视图层次结构没有为约束做好准备”。

enter image description here

在以下两个地方调用

setupDownView

@IBOutlet weak var cardTags: UIView! {didSet { setupDownView(view: cardTags)}}
@IBOutlet weak var cardContent: UIView! {
    didSet {
        setupDownView(view: cardContent)
        let tap = UILongPressGestureRecognizer(
            target: self,
            action: #selector(QuizViewController.tapDownHandler)
        )
        tap.minimumPressDuration = 0
        cardContent.addGestureRecognizer(tap)
    }
}

2 个答案:

答案 0 :(得分:3)

在视图位于层次结构中之后,需要添加约束。因此addSubview来电必须才能 addConstraint来电。

同时确保在其超级视图上调用addConstraint,而不是downView,并且添加从constraintsWithVisualFormat:返回的所有约束,而不是只有第一个。

private func setupDownView(view: UIView) {
    let downView = try? DownView(frame: view.bounds, markdownString: "")
    downView!.translatesAutoresizingMaskIntoConstraints = false
    view.addSubview(downView!);

    let viewsDict = ["view": downView!]
    view.addConstraints(NSLayoutConstraint.constraints(
        withVisualFormat: "V:|-0-[view]-0-|",
        options: [],
        metrics: nil,
        views: viewsDict))
    view.addConstraints(NSLayoutConstraint.constraints(
        withVisualFormat: "H:|-0-[view]-0-|",
        options: [],
        metrics: nil,
        views: viewsDict))

    view.layoutIfNeeded()
}

答案 1 :(得分:1)

从iOS 8开始,您不必考虑添加约束的视图,只需激活它们即可。对于个别约束,只需将.isActive设置为true即可。要激活整个约束数组,请使用NSLayoutConstraint.activate()便捷方法。

对于您的代码,而不是:

view.addConstraints(NSLayoutConstraint.constraints(
    withVisualFormat: "V:|-0-[view]-0-|",
    options: [],
    metrics: nil,
    views: viewsDict))

您将使用:

NSLayoutConstraint.activate(NSLayoutConstraint.constraints(
    withVisualFormat: "V:|-0-[view]-0-|",
    options: [],
    metrics: nil,
    views: viewsDict))

这是有效的,因为约束已经知道它们引用了哪个或哪些视图, Cocoa Cocoa Touch 可以在视图层次结构中找出适当的视图来添加约束,根据视图的相关方式(例如兄弟姐妹,父母/孩子,其他)可能会很棘手。

同样的警告适用于此。您需要确保视图位于视图层次结构之前激活约束,否则您将收到错误。因此,在激活约束之前执行.addSubview