如何以编程的方式删除从Storyboard中添加的约束?

57

我已经使用谷歌搜索但没有找到答案。所以我需要问一下。 我有一个主屏幕。当用户登录时,它将显示以下视图: enter image description here 现在当用户注销并访问主页时,他会看到上面的布局,但是中心框中的布局不会显示出来。如果我将该布局隐藏,则现在显示如下所示: enter image description here

我想将第三个布局向上移动一点,以消除白色空间。

我已经在故事板中使用约束添加了约束。现在需要从编程中删除约束,并添加一个约束,将布局设置为第一个布局的下方。


1
请查看此博客:https://dev59.com/lXTYa4cB1Zd3GeqP0OhR - Divya Bhaloidiya
@Mrunal。是的,我正在处理这个问题。实际上,我在日志中遇到了一些约束方面的警告。 - Dharmik
10个回答

54

正如@Henit所提到的,你也可以为约束设置IBOutlet。

例如,

@property(weak, nonatomic) IBOutlet NSLayoutConstraint *viewHeight;

现在,你可以像这样移除约束:

[myView removeConstraint: viewHeight];

或者,如果您想要删除与您的视图相关的所有/多个约束条件,则:

[myView removeConstraints: constraintsArrayHere]; // custom array of constraints references
[myView removeConstraints: [myView constraints]]; //all constraints

稍后您可以使用addConstraintaddConstraints方法以同样的方式添加新限制。

如需更多详细信息,请参阅苹果公司的文档这里

希望这能有所帮助。


RemoveConstraints 对我无效。经过几个小时的费解工作,Thein 的答案——将约束设置为非活动状态,是我所需要的解决办法。 - Chucky

37

removeConstraints将来会被弃用。

您可以使用以下内容作为替代方案

viewHeight.active = NO;

必须弃用,因为这是对我有效的!真是让人费解的问题。 - Chucky

19

针对@Megamind的回答进行补充:你可以使用NSLayoutConstraintactive属性。为两种情况分别设置不同的约束条件,并根据登录状态只激活其中一个。

在InterfaceBuilder中,active属性奇怪地被称为Installed

登录约束注册约束

然后在你的代码中在两者之间切换:

- (void)setupRegistrationView
{        
    _loadingIndicatorTopConstraintLogin.active = NO;
    _loadingIndicatorTopConstraintRegister.active = YES;
}

- (void)setupLoginView
{        
    _loadingIndicatorTopConstraintLogin.active = YES;
    _loadingIndicatorTopConstraintRegister.active = NO;
}

顺便提一句,使用新的UIStackView可能会为您的情况提供更优雅的解决方案,但这是另一个话题。


16

Swift 4

@IBOutlet weak var viewHeight: NSLayoutConstraint!
viewHeight.isActive = false    

开心编程 :)


16

从iOS 10+开始,您可以简单地遍历视图的所有约束并将其取消激活。例如,如果您想查找并删除视图的高度约束,则可以执行以下操作:

for constraint in constraints {
    guard constraint.firstAnchor == heightAnchor else { continue }
    constraint.isActive = false
    break
}

替代方案

这甚至只需要一行代码。如果你在视图中,你可以直接写:

constraints.first { $0.firstAnchor == heightAnchor }?.isActive = false

第二种选择

不要使用故事板 - 它们存在一些问题,在未来,例如使用SwiftUI,它们将过时。


Storyboard并不是邪恶的。SwiftUI是另一个UI框架。使用Storyboard和xib来定义UI并不是不合理的(特别是对于约束来说!)。 - Frizlab
1
稍微修改了一下这个句子;-) - blackjacx

12

在用户注销时,获取需要隐藏的视图高度约束的 IBOutlet。

@property(weak, nonatomic) IBOutlet NSLayoutConstraint *viewHeight;

NSLayoutConstraint 类中有一个属性叫做constant。 当用户登录/注销时,您需要设置它。

viewHeight.constant = isLoggedIn ? 30.0 : 0.0;

希望这能有所帮助。


2

您还可以使用其他方法。在第三个布局和第一个布局之间添加垂直间距约束,为30。然后在控制器中添加对约束的引用。

self.verticalSpacingFromThirdToFirstConstraint.constant = isLoggedIn ? 30.0 : 0.0

注意,在这种情况下,您不应为中间视图添加高度约束。只需添加四个尾随、前导、顶部(到第一个布局)和底部(到第三个布局)约束即可。


2

如果你无法从界面构建器中访问约束,则可以使用以下方式更新约束:

    let topConstraint = view.constraints.first(where: { $0.firstAttribute == .top })
    topConstraint?.constant = 20

“view”是你尝试更新其约束的任何视图。 采用这种方法存在一些缺点,因为你可能会有一个以上与所涉及视图相关联的顶部约束。


1
您可以为您想要隐藏的视图添加高度约束。 并在您的viewcontroller.h文件中添加一个NSlayoutHeightcontraint输出。然后,您可以在需要的任何位置在您的viewcontroller.m文件中调用该heightConstrain输出。在您想要隐藏此UIview的位置添加此代码:
_heightconstrainOutlet.constant=0;

它将使高度变为零。因此,您的底部视图也将覆盖该区域。如果您的底部视图具有高度约束和底部空间到容器约束?根据您的要求,只需删除其中任何一个即可。谢谢。

1

我遇到了一个类似的问题,我的tableView在一个cell中还有另一个tableView,当cell被重用时,高度的约束会堆积起来。为了解决这个问题,我做了以下操作:

constraints.filter({$0.firstAnchor == heightAnchor }).forEach{ $0.isActive = false }

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