使用 ib action-Swift 删除尾随约束

Posted

技术标签:

【中文标题】使用 ib action-Swift 删除尾随约束【英文标题】:Remove trailing constraint with ib action- Swift 【发布时间】:2020-08-28 18:57:15 【问题描述】:

我创建了一个视图控制器,顶部有一个分段控制器。当您点击分段控制器时,它只是充当一个按钮,并通过调用将其更改为相应尺寸的函数来更改控制器内部的 imageView 是纵向模式还是横向模式。

我的问题是我改变它的方式是我只是向 imageView 添加了约束,但是当更改为横向模式时,尾随约束并没有被删除。

而且,这是将 imageView 更改为纵向的代码(imageView 已经具有顶部和底部约束):

func portraitContraints() 
    
    NSLayoutConstraint.activate ([
    // the trailing contraint
    imageView.trailingAnchor.constraint(equalTo: viewContainer.safeAreaLayoutGuide.trailingAnchor, constant: -75), // this is the contraints that doesn't get removed
    // the leading contraints
    imageView.leadingAnchor.constraint(equalTo: viewContainer.safeAreaLayoutGuide.leadingAnchor, constant: 75
    ])
   
    // the aspect ratio contraints
    imageView.addConstraint(NSLayoutConstraint(item: self.imageView as Any,attribute: .height,relatedBy: .equal,toItem: self.imageView,attribute: .width,multiplier: (4.0 / 3.0),constant: 0))

这是将 imageView 更改为横向的代码:

func landscapeContraints() 
    
    NSLayoutConstraint.activate([
    // the trailing contraints
    imageView.trailingAnchor.constraint(equalTo: viewContainer.safeAreaLayoutGuide.trailingAnchor, constant: 0),
    // the leading contraint
    imageView.leadingAnchor.constraint(equalTo: viewContainer.safeAreaLayoutGuide.leadingAnchor, constant: 0)
    ])
    // the aspect ratio contraint
    imageView.addConstraint(NSLayoutConstraint(item: self.imageView as Any,attribute: .height,relatedBy: .equal,toItem: self.imageView,attribute: .width,multiplier: (9.0 / 16.0),constant: 0))

这段代码就像一个魅力,除了唯一的问题是纵向模式的尾随约束将保留在视图上(-75 常量约束)。

风景看起来像这样(注意右边的常数是-75):

人像是这样的:

【问题讨论】:

【参考方案1】:

您可以通过添加具有不同优先级的两个比率约束来做到这一点。更改优先级以使所需的比率“活跃”。

并且,创建前导和尾随约束变量,以便您可以更改它们的常量。

这是一个简单的例子:

class ToggleConstraintsViewController: UIViewController 
    
    let imageView = UIImageView()
    
    var isPortrait: Bool = true
    
    var portraitConstraint: NSLayoutConstraint!
    var landscapeConstraint: NSLayoutConstraint!
    var leadingConstraint: NSLayoutConstraint!
    var trailingConstraint: NSLayoutConstraint!
    
    override func viewDidLoad() 
        super.viewDidLoad()
        
        imageView.backgroundColor = .blue
        
        imageView.translatesAutoresizingMaskIntoConstraints = false
        
        view.addSubview(imageView)
        
        let g = view.safeAreaLayoutGuide
        
        portraitConstraint = imageView.heightAnchor.constraint(equalTo: imageView.widthAnchor, multiplier: 4.0/3.0)
        portraitConstraint.priority = .defaultHigh
        landscapeConstraint = imageView.heightAnchor.constraint(equalTo: imageView.widthAnchor, multiplier: 9.0/16.0)
        landscapeConstraint.priority = .defaultLow
        
        leadingConstraint = imageView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 75.0)
        trailingConstraint = imageView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -75.0)
        
        NSLayoutConstraint.activate([
            // y-position constraint does not change
            imageView.centerYAnchor.constraint(equalTo: g.centerYAnchor),
            
            // these will have their priorities changed when desired
            portraitConstraint,
            landscapeConstraint,
            
            // these will have their constants changed when desired
            leadingConstraint,
            trailingConstraint,
        ])
        
        let t = UITapGestureRecognizer(target: self, action: #selector(self.toggleOrientation(_:)))
        view.addGestureRecognizer(t)
    

    @objc func toggleOrientation(_ g: UITapGestureRecognizer) -> Void 
        isPortrait.toggle()
        
        portraitConstraint.priority = isPortrait ? .defaultHigh : .defaultLow
        landscapeConstraint.priority = isPortrait ? .defaultLow : .defaultHigh
        
        leadingConstraint.constant = isPortrait ? 75.0 : 0.0
        trailingConstraint.constant = isPortrait ? -75.0 : 0.0
        
    
    

每次点击视图时,imageView 的宽高比都会发生变化,前导/尾随约束常量也会发生变化。

【讨论】:

是的,这行得通。但问题是我不仅需要改变纵横比......我还需要改变前导和尾随约束的常数。 (所以横向需要 0 常量,纵向需要 75(-75))谢谢! @willscarter - 抱歉,我错过了第一次查看时前导/尾随的变化。我更新了我的答案并对此进行了修复。【参考方案2】:

尝试在添加新约束之前删除旧约束。这是 Apples 关于如何做到这一点的文档:https://developer.apple.com/documentation/uikit/uiview/1622593-removeconstraints

【讨论】:

以上是关于使用 ib action-Swift 删除尾随约束的主要内容,如果未能解决你的问题,请参考以下文章

为啥这个简单的自动布局在 IB 中崩溃了?

使用乘数的 Swift 约束与尾随但不领先

Xcode IB 警告 UICollectionViewCell 中 UIStackView 的位置不明确,尽管它不应该是

在两个视图之间添加尾随约束

如何消除“前导和尾随约束……已经存在中心约束”警告

使用自动布局将 UIButton 添加到自定义单元格