未按预期应用约束

问题描述 投票:0回答:1

我有一个自定义的UITextField,可以在多个地方使用,但是在我使用的几个页面上,它的约束存在一个奇怪的问题。自定义类有一些我在初始化时添加的内容:

  • 我使用顶部,左侧和右侧约束将UILabel添加为子视图的UITextField。当UITextField的awakeFromNib函数执行时,将调用此方法]
class FormTextField: UITextField {
    override func awakeFromNib() {
        self.layer.masksToBounds = true
        self.addErrorLabel()
    }

    ...

    private func addErrorLabel() {
        errorLabel = UILabel(frame: CGRect(x: self.frame.minX, y: self.frame.maxY-5, width: self.frame.width, height: self.frame.height))
        errorLabel.textColor = UIColor.red
        errorLabel.backgroundColor = UIColor.black
        errorLabel.font = UIFont.systemFont(ofSize: 12.0)
        errorLabel.text = ""
        errorLabel.alpha = 0.0
        errorLabel.numberOfLines = 0

        errorLabel.textAlignment = YTPAppManager.language == .arabic ? .right : .left

        if (self.textAlignment != .center) { self.textAlignment = YTPAppManager.language == .arabic ? .right : .left }

        errorLabel.translatesAutoresizingMaskIntoConstraints = false

        self.superview?.addSubview(errorLabel)

        let topConstraint = NSLayoutConstraint(item: errorLabel!, attribute: .top, relatedBy: .equal, toItem: self, attribute: .bottom, multiplier: 1.0, constant: 0.0)
        let leftConstraint = NSLayoutConstraint(item: errorLabel!, attribute: .left, relatedBy: .equal, toItem: self, attribute: .left, multiplier: 1.0, constant: 0.0)
        let rightConstraint = NSLayoutConstraint(item: errorLabel!, attribute: .right, relatedBy: .equal, toItem: self, attribute: .right, multiplier: 1.0, constant: 0.0)

        topConstraint.priority = UILayoutPriority(1.0)
        leftConstraint.priority = UILayoutPriority(1.0)
        rightConstraint.priority = UILayoutPriority(1.0)

        self.superview?.addConstraints([
            topConstraint, leftConstraint, rightConstraint
        ])
    }

    ...
}

  • 我也有一个CALayer,它被添加为UITextField的SubLayer,在视图出现后我从ViewController调用它。
class FormTextField: UITextField {
    func addBottomBorder(color: CGColor? = UIColor(red: 0.78, green: 0.78, blue: 0.78, alpha: 1.0).cgColor) {
        removeBottomBorder() { _ in
            let border = CALayer()
            let width = CGFloat(2.0)
            border.backgroundColor = color
            border.borderColor = color
            border.frame = CGRect(x: 0, y: self.frame.size.height - width, width: self.frame.size.width, height: width)
            border.borderWidth = width
            border.accessibilityValue = "bottomBorder"

            self.layer.addSublayer(border)
        }
    }
}

class AViewController: UIViewController {

    @IBOutlet weak var exampleTextField: FormTextField!

    override func viewDidAppear(_ animated: Bool) {
        exampleTextField.addBottomBorder
        self.view.setNeedsLayout()
        self.layoutIfNeeded()

        super.viewDidAppear(animated)
    }

    ...
}

我在3个不同的视图上看到了3个不同的结果,尽管它们的设置都完全相同。视图架构为:View -> ScrollView -> View -> FormTextField。在所有视图中,文本字段的超级视图等于32的前导空间约束,而超级视图等于32的尾随空间约束。

现在这是我看到的不一致之处:

1)一种视图看起来非常好,并且一切看起来都应该正确。底部边框跨越实际文本字段的宽度,并且错误标签显示在左侧。

enter image description here

2)另一种观点是部分正确的。底部边框跨越实际文本字段的宽度,但是错误标签显示在右侧而不是左侧。

enter image description here

3)带有它的最后一个视图是完全错误的。底部边框仅跨越文本框的一部分(它似乎可以校正情节提要中使用的设备的宽度,但在大屏幕iPhone上使用时看起来不正确),并且错误标签显示在右侧而不是左边也是。

enter image description here

enter image description here

我已经一遍又一遍地检查,在实现它们的方式上找不到单一的差异。它们对自己的超级视图都具有相同的约束,在所有三个不同的视图控制器的addBottomBorder中调用viewDidAppear,等等。

我的猜测是,这与UITextField上的布局约束以及初始化期间可能出现的怪异竞争条件有关,但是我迷路了。我做错了什么导致结果不一致?

我有一个自定义的UITextField,可以在多个地方使用,但是在我使用的几个页面上,它的约束存在一个奇怪的问题。自定义类有几件我要添加的内容...

ios swift uitextview nslayoutconstraint
1个回答
0
投票

我还认为这与设置约束有关,建议您使用以下功能重新进行设置:

extension UIView {

    func anchors (top:NSLayoutYAxisAnchor? , leading:NSLayoutXAxisAnchor? , bottom : NSLayoutYAxisAnchor? , trailing: NSLayoutXAxisAnchor? , padding : UIEdgeInsets = .zero){

        translatesAutoresizingMaskIntoConstraints = false

        if let top = top {
            topAnchor.constraint(equalTo: top , constant: padding.top).isActive = true
        }
        if let leading = leading {
            leadingAnchor.constraint(equalTo: leading , constant: padding.left).isActive = true
        }
        if let bottom = bottom {
            bottomAnchor.constraint(equalTo: bottom , constant: -padding.bottom).isActive = true
        }
        if let trailing = trailing {
            trailingAnchor.constraint(equalTo: trailing , constant: -padding.right).isActive = true
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.