2

I have a UITextField & UIButton placed inside a vertical UIStackView. Programatically, I've added a UIView to serve as an underline of the UITextField.

The problem comes when I compile the code. The line is longer than the text field. I've printed the width of all of the objects above and it says 335.

I call this function in viewWillAppear and the line is longer. If I call it in viewDidAppear, the line is the exact width of the UITextField but you can see the button and text field flash very briefly before updating the view. What am I doing wrong? enter image description here enter image description here

override func viewDidLoad()  {
    super.viewDidLoad()
    observeKeyboardNotifications()
    textFieldDelegate()
    setupRegisterButton()

}

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
     setupTextFields()
}

func setupTextFields() {

    emailTextField.leftViewMode = .always
    let emailIconView = UIImageView()
    emailIconView.frame = CGRect(x: 0, y: 0, width: 23, height: 17)
    emailIconView.image = UIImage(named: "icon_email")
    let bgIconView = UIView(frame: CGRect(x: 0, y: 0, width: 28, height: 17))
    bgIconView.addSubview(emailIconView)
    emailTextField.leftView = bgIconView

    emailTextField.tintColor = .white
    emailTextField.textColor = .white
    emailTextField.backgroundColor = .red
    emailTextField.borderStyle = .roundedRect
    let bottomLineEmail = CALayer()
    bottomLineEmail.frame = CGRect(x: 0, y: 29, width: emailTextField.frame.width, height: 1)
    print("Email width", emailTextField.frame.width)
    print("button width", retrievePasswordButton.frame.width)
    print("line width", bottomLineEmail.frame.width)
    bottomLineEmail.backgroundColor = UIColor.white.cgColor
    emailTextField.layer.addSublayer(bottomLineEmail)
    //emailTextField.backgroundColor = .clear
    emailTextField.attributedPlaceholder = NSAttributedString(string     : emailTextField.placeholder!,
                                                              attributes : [NSAttributedStringKey.foregroundColor: Colors.authTextFieldPlaceholderColor])
    retrievePasswordButton.isEnabled = false
    handleTextFields()
}
Dani
  • 3,427
  • 3
  • 28
  • 54
  • Don't add views/layers in `viewWillAppear`, the method can be called multiple times. No, the frames won't be correct in `viewWillAppear`. Use `viewDidLayoutSubviews`. Also this would be much simpler with a simpler `UIView` and autolayout. – Sulthan Jan 17 '19 at 11:58
  • @Sulthan calling it in `viewDidLayoutSubviews` didnt work as expected though. The width of the underline is still longer than the text field itself. – Dani Jan 17 '19 at 12:03
  • @Dani instead of adding layer why don't you add a view of that size and constraint inside of your stack view. – Jarvis The Avenger Jan 17 '19 at 12:09
  • @JarvisTheAvenger yes, that's what I've ended up doing. Seems to be a lot easier. Thank you – Dani Jan 17 '19 at 12:27
  • @Dani Great to hear that. Happy Coding. – Jarvis The Avenger Jan 17 '19 at 12:27

1 Answers1

1

I checked it personally it works in ViewWillLayoutSubviews

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews();
    self.setupTextFields()
}

and viewDidAppear

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    self.setupTextFields();
}

proof

Talha Ahmad Khan
  • 3,416
  • 5
  • 23
  • 38