复制IB创建的约束到另一个UIView

13

我有一个屏幕上包含其他视图元素的 UITableView 列表。 当没有交易需要显示时,我计划将此列表替换为另一个视图。 为此,我需要复制附加到 UITableView 的所有约束,并将它们添加到新的 UIView 中。

屏幕截图

我尝试复制 .constraints() 属性值,但返回 nil,因为这些约束附加到父视图。从 superview 获取约束会返回所有附加到其他子视图的约束。

是否有一种快速的方法可以将一个 UIView 中的约束复制并添加到另一个视图中?

2个回答

19

没有快速的方法。

我使用了循环遍历父视图的约束来完成它。

Objective-C

+ (void)copyConstraintsFromView:(UIView *)sourceView toView:(UIView *)destView
{
    for (NSLayoutConstraint *constraint in sourceView.superview.constraints) {
        if (constraint.firstItem == sourceView)
        {
            [sourceView.superview addConstraint:[NSLayoutConstraint constraintWithItem:destView attribute:constraint.firstAttribute relatedBy:constraint.relation toItem:constraint.secondItem attribute:constraint.secondAttribute multiplier:constraint.multiplier constant:constraint.constant]];
        }
        else if (constraint.secondItem == sourceView)
        {
            [sourceView.superview addConstraint:[NSLayoutConstraint constraintWithItem:constraint.firstItem attribute:constraint.firstAttribute relatedBy:constraint.relation toItem:destView attribute:constraint.secondAttribute multiplier:constraint.multiplier constant:constraint.constant]];
        }
    }
}

Swift

static func copyConstraints(fromView sourceView: UIView, toView destView: UIView) {
    guard let sourceViewSuperview = sourceView.superview else {
        return
    }
    for constraint in sourceViewSuperview.constraints {
        if constraint.firstItem as? UIView == sourceView {
            sourceViewSuperview.addConstraint(NSLayoutConstraint(item: destView, attribute: constraint.firstAttribute, relatedBy: constraint.relation, toItem: constraint.secondItem, attribute: constraint.secondAttribute, multiplier: constraint.multiplier, constant: constraint.constant))
        } else if constraint.secondItem as? UIView == sourceView {
            sourceViewSuperview.addConstraint(NSLayoutConstraint(item: constraint.firstItem, attribute: constraint.firstAttribute, relatedBy: constraint.relation, toItem: destView, attribute: constraint.secondAttribute, multiplier: constraint.multiplier, constant: constraint.constant))
        }
    }
}

注意

记得在将destView添加到视图层次结构后再复制约束。


4

不,系统内没有为此构建的功能。

NSLayoutConstraint对象是不可变的,除了它的constant优先级之外,因此一旦创建了该对象,您就无法简单地将“相同”的约束应用于另一个视图(其中“相同”表示对象标识或对象相等)。

如果性能允许,我会将表格视图和无数据对应视图都设置为兄弟,并使用一个帮助函数在每个视图上安装等效的约束,使它们布局相同,但一个位于另一个上方。然后,我只需使用hidden属性交换哪个视图可见。

然而,如果您真的想在运行时以一般方式将一个视图的约束复制到另一个视图中,则必须编写一个实用程序方法,从最祖先的父视图开始进行递归搜索,该父视图可能具有影响视图被复制的任何约束,并创建一个应用于另一个视图的重复约束。这样的函数可能已经在AL辅助库之一中编写,例如FLKAutoLayout。


我最终在IB中为另一个视图创建了约束。编写递归查找的方法很混乱,因为约束也可能与兄弟姐妹有关。 - atastrophic

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接