不冲突的冲突约束(快速)

时间:2020-10-16 22:04:18

标签: ios swift

旋转手机时,我正在重新排列以下三个视图:

enter image description here enter image description here

我将约束设置如下:

    var narrowConstraints: [NSLayoutConstraint] = []
    var wideConstraints: [NSLayoutConstraint] = []

    func setConstraints1() {
        
        let cv1Height: CGFloat = 325
        let cv3Height: CGFloat = 125
        
        cv1.translatesAutoresizingMaskIntoConstraints = false
        cv2.translatesAutoresizingMaskIntoConstraints = false
        cv3.translatesAutoresizingMaskIntoConstraints = false
        
        let g = view.safeAreaLayoutGuide
        
        // wh
        narrowConstraints = [
            
            // set cv1 height
            cv1.heightAnchor.constraint(equalToConstant: cv1Height),
            // lock top, left and right to safe area
            cv1.topAnchor.constraint(equalTo: g.topAnchor),
            cv1.leadingAnchor.constraint(equalTo: g.leadingAnchor),
            cv1.trailingAnchor.constraint(equalTo: g.trailingAnchor),

            // lock left and right to safe area
            cv2.leadingAnchor.constraint(equalTo: g.leadingAnchor),
            cv2.trailingAnchor.constraint(equalTo: g.trailingAnchor),
            
            // lock top of cv2 to bottom of cv1
            cv2.topAnchor.constraint(equalTo: cv1.bottomAnchor),
            // lock bottom of cv2 to top of cv3
            cv2.bottomAnchor.constraint(equalTo: cv3.topAnchor),
            
            // set cv3 height
            cv3.heightAnchor.constraint(equalToConstant: cv3Height),
            // lock left, right and bottom to safe area
            cv3.leadingAnchor.constraint(equalTo: g.leadingAnchor),
            cv3.trailingAnchor.constraint(equalTo: g.trailingAnchor),
            cv3.bottomAnchor.constraint(equalTo: g.bottomAnchor),
        ]
        
        wideConstraints = [

            // lock top, bottom, and left to safe area
            cv1.topAnchor.constraint(equalTo: g.topAnchor),
            cv1.bottomAnchor.constraint(equalTo: g.bottomAnchor),
            cv1.leadingAnchor.constraint(equalTo: g.leadingAnchor),
            // lock right side of cv1 to left side of cv2
            cv1.trailingAnchor.constraint(equalTo: cv2.leadingAnchor),
            
            // lock right side of cv2 to safe area
            cv2.trailingAnchor.constraint(equalTo: g.trailingAnchor),
            // lock top of cv2 to safe area
            cv2.topAnchor.constraint(equalTo: g.topAnchor),
            // lock bottom of cv2 to top of cv3
            cv2.bottomAnchor.constraint(equalTo: cv3.topAnchor),

            // set cv3 height
            cv3.heightAnchor.constraint(equalToConstant: cv3Height),
            // lock bottom and right side of cv3 to safe area
            cv3.trailingAnchor.constraint(equalTo: g.trailingAnchor),
            cv3.bottomAnchor.constraint(equalTo: g.bottomAnchor),
            
            // make them all equal widths
            cv2.widthAnchor.constraint(equalTo: cv1.widthAnchor),
            cv3.widthAnchor.constraint(equalTo: cv2.widthAnchor),            
        ]
        
        if view.frame.width > view.frame.height {
            // if landscape
            NSLayoutConstraint.deactivate(narrowConstraints)
            NSLayoutConstraint.activate(wideConstraints)
        }
        else { // portrait
            NSLayoutConstraint.deactivate(wideConstraints)
            NSLayoutConstraint.activate(narrowConstraints)
        }
    }

    override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
        super.viewWillTransition(to: size, with: coordinator)
        coordinator.animate(alongsideTransition: { _ in
            if size.width > size.height {
                // we're transitioning to wider than tall
                NSLayoutConstraint.deactivate(self.narrowConstraints)
                NSLayoutConstraint.activate(self.wideConstraints)
            } else {
                // we're transitioning to taller than wide
                NSLayoutConstraint.deactivate(self.wideConstraints)
                NSLayoutConstraint.activate(self.narrowConstraints)
            }
        }, completion: {
            _ in
            // if you want to do something after the transition
            //self.cv2.setNeedsDisplay()
        })
    }

一切似乎都正常工作-除了以下错误消息:

2020-10-16 14:33:57.364778-0600 ViewPositions2[38358:6108060] [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. 
(
    "<NSLayoutConstraint:0x6000033a9130 UIView:0x7fb41950ad90.height == 325   (active)>",
    "<NSLayoutConstraint:0x6000033aa800 UIView:0x7fb41950ad90.top == UILayoutGuide:0x6000029bcb60'UIViewSafeAreaLayoutGuide'.top   (active)>",
    "<NSLayoutConstraint:0x6000033aa3f0 V:[UIView:0x7fb41950ad90]-(0)-[UIView:0x7fb41950dec0]   (active)>",
    "<NSLayoutConstraint:0x6000033a9ea0 UIView:0x7fb41950dec0.bottom == UIView:0x7fb41950e8f0.top   (active)>",
    "<NSLayoutConstraint:0x6000033a9c70 UIView:0x7fb41950e8f0.height == 125   (active)>",
    "<NSLayoutConstraint:0x6000033aa2b0 UIView:0x7fb41950e8f0.bottom == UILayoutGuide:0x6000029bcb60'UIViewSafeAreaLayoutGuide'.bottom   (active)>",
    "<NSLayoutConstraint:0x60000339ff20 'UIView-Encapsulated-Layout-Height' UIView:0x7fb41950f1c0.height == 375   (active)>",
    "<NSLayoutConstraint:0x60000339b840 'UIViewSafeAreaLayoutGuide-bottom' V:[UILayoutGuide:0x6000029bcb60'UIViewSafeAreaLayoutGuide']-(0)-|   (active, names: '|':UIView:0x7fb41950f1c0 )>",
    "<NSLayoutConstraint:0x60000339b7a0 'UIViewSafeAreaLayoutGuide-top' V:|-(0)-[UILayoutGuide:0x6000029bcb60'UIViewSafeAreaLayoutGuide']   (active, names: '|':UIView:0x7fb41950f1c0 )>"
)

Will attempt to recover by breaking constraint 
<NSLayoutConstraint:0x6000033a9130 UIView:0x7fb41950ad90.height == 325   (active)>

通过反复试验,我发现如果cv1Heightcv2Height的总和超过375(横向视图高度),则会出现此错误消息。

但是,不仅在风景中我会停用narrowConstraints,而且cv1永远不会在风景中cv3之上!

为什么会发生这种冲突?我该如何预防??

1 个答案:

答案 0 :(得分:0)

您可以将固定高度约束的优先级设置为低于.required

let fixedHeightConstraint = cv1.heightAnchor.constraint(equalToConstant: cv1Height)
fixedHeightConstraint.priority = .required - 1;