У меня есть пользовательский UITextField, который я использую в нескольких местах, но у меня странная проблема с ограничениями только на нескольких страницах, которые я использую. У пользовательского класса есть несколько вещей, которые я добавляю при инициализации:
- UILabel, который я добавляю как подпредставление, используя ограничения top, left и right для UITextField. Это вызывается, когда
awakeFromNib
функция UITextField выполняет
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, который добавляется как SubLayer UITextField, который я вызываю из 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) Один вид выглядит отлично и все выглядит точно так, как должно. Нижняя граница охватывает ширину фактического текстового поля, а с левой стороны появляется метка ошибки.

2) Другой вид является частично правильным. Нижняя граница охватывает ширину фактического текстового поля, но вместо левой стороны появляется метка ошибки.

3) Последний взгляд с ним совершенно не прав. Нижняя граница охватывает только часть текстового поля (кажется, что она корректируется по ширине устройства, используемого в раскадровке, но выглядит некорректно при прямом эфире на iPhone с большим экраном), а метка ошибки отображается справа вместо левой тоже.


Я проверял снова и снова снова и не могу найти единственную разницу в способах, которыми я их реализовал. Все они имеют одинаковые ограничения для своего суперпредставления, addBottomBorder
вызывается в viewDidAppear
во всех трех различных контроллерах представления и т. Д. c.
Я предполагаю, что это как-то связано с ограничениями макета на UITextField и, возможно, странное состояние гонки во время инициализации, но я заблудился. Что я делаю неправильно, что приводит к противоречивым результатам?