添加文本字段时无法使用锚点激活约束

Unable to activate constraint with anchors while adding a textfield

不久前我开始通过故事板创建屏幕。

最近我确信以编程方式进行。

目前我运行遇到以下错误:

Terminating app due to uncaught exception 'NSGenericException', reason: 'Unable to activate constraint with anchors and because they have no common ancestor. Does the constraint or its anchors reference items in different view hierarchies? That's illegal.'

import UIKit

class ViewController: UIViewController {

   var emailTextField: UITextField {

        let tf = UITextField()
        tf.placeholder = "email";
        tf.backgroundColor = UIColor(white: 0, alpha: 0.03)
        tf.borderStyle = .roundedRect
        tf.font = UIFont.systemFont(ofSize: 14)

        return tf
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        view.backgroundColor = .white

        view.addSubview(emailTextField)

        emailTextField.anchor(top: view.topAnchor, left: view.leftAnchor, bottom: nil, right: view.rightAnchor, paddingTop: 40, paddingLeft: 20, paddingBottom: 0, paddingRight: 20, width: 0, height: 40)
    }

}

我创建了一个函数来将我的元素锚定在 Extensions.swift:

import UIKit

extension UIView {

    func anchor(top: NSLayoutYAxisAnchor?, left: NSLayoutXAxisAnchor?, bottom: NSLayoutYAxisAnchor?, right: NSLayoutXAxisAnchor?, paddingTop: CGFloat, paddingLeft: CGFloat, paddingBottom: CGFloat, paddingRight: CGFloat, width: CGFloat, height: CGFloat) {

        translatesAutoresizingMaskIntoConstraints = false

        if let top = top {
            self.topAnchor.constraint(equalTo: top, constant: paddingTop).isActive = true
        }

        if let left = left {
            self.leftAnchor.constraint(equalTo: left, constant: paddingLeft).isActive = true
        }

        if let bottom = bottom {
            self.bottomAnchor.constraint(equalTo: bottom, constant: -paddingBottom).isActive = true
        }

        if let right = right {
            self.rightAnchor.constraint(equalTo: right, constant: -paddingRight).isActive = true
        }

        if width != 0 {
            widthAnchor.constraint(equalToConstant: width).isActive = true
        }

        if height != 0 {
            heightAnchor.constraint(equalToConstant: height).isActive = true
        }


    }
}

另外,我删除了Info.plist中的Application Scene Manifest。

我希望我的项目支持即将推出的 iOS 版本,从 13.0 开始。 不过我不想使用新框架SwiftUI。

有什么特别需要注意的地方(例如场景代理)吗?

提前致谢!

你需要改变这个

var emailTextField: UITextField {

    let tf = UITextField()
    tf.placeholder = "email";
    tf.backgroundColor = UIColor(white: 0, alpha: 0.03)
    tf.borderStyle = .roundedRect
    tf.font = UIFont.systemFont(ofSize: 14)

    return tf
}

进入这个

var emailTextField: UITextField = {

    let tf = UITextField()
    tf.placeholder = "email";
    tf.backgroundColor = UIColor(white: 0, alpha: 0.03)
    tf.borderStyle = .roundedRect
    tf.font = UIFont.systemFont(ofSize: 14)

    return tf
}()

在当前版本中 emailTextField 是计算 属性,因此,每次您访问它时,编译器都会创建一个新实例(它像函数一样工作,而不是变量)。

在您添加其约束时,Textfield 无法获取其父视图。下面的代码对我有用。我将当前视图作为参数传递给 anchor() 方法,并在其中添加 emailTextField 作为子视图。

class ViewController: UIViewController {

  var emailTextField:UITextField = {
     let tf = UITextField()
     tf.placeholder = "email";
     tf.backgroundColor = UIColor(white: 0, alpha: 0.03)
     tf.borderStyle = .roundedRect
     tf.font = UIFont.systemFont(ofSize: 14)
     return tf
  }()

  override func viewDidLoad() {
      super.viewDidLoad()

      view.backgroundColor = .white
      emailTextField.anchor(top: view.safeAreaLayoutGuide.topAnchor, left: view.leftAnchor, bottom: nil, right: view.rightAnchor, paddingTop: 40, paddingLeft: 20, paddingBottom: 0, paddingRight: 20, width: 0, height: 40, view:view)
   }


 }


extension UIView {

     func anchor(top: NSLayoutYAxisAnchor?, left: NSLayoutXAxisAnchor?, bottom: NSLayoutYAxisAnchor?, right: NSLayoutXAxisAnchor?, paddingTop: CGFloat, paddingLeft: CGFloat, paddingBottom: CGFloat, paddingRight: CGFloat, width: CGFloat, height: CGFloat, view:UIView) {

        translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(self)
        if let top = top {
           self.topAnchor.constraint(equalTo: top, constant: paddingTop).isActive = true
        }

        if let left = left {
             self.leftAnchor.constraint(equalTo: left, constant: paddingLeft).isActive = true
        }

         if let bottom = bottom {
             self.bottomAnchor.constraint(equalTo: bottom, constant: -paddingBottom).isActive = true
         }

         if let right = right {
            self.rightAnchor.constraint(equalTo: right, constant: -paddingRight).isActive = true
        }

         if width != 0 {
            widthAnchor.constraint(equalToConstant: width).isActive = true
         }

         if height != 0 {
             heightAnchor.constraint(equalToConstant: height).isActive = true
         }
      }
}