将 UIViewController 视图属性设置为没有故事板/笔尖的自定义 UIView 类

2024-03-06

我有一个UIViewController called LoginViewController。我想建立这样的观点LoginViewController 完全以编程方式在一个习惯中UIView类称为LoginView而不是在我的内部构建所有元素LoginViewController。这样我就可以防止控制器类(MVC)中的“查看”代码。

在下面的代码中,我设置了我的视图LoginViewController to my LoginView为简单起见,仅包含 2UILabels

class LoginViewController: UIViewController {

override func loadView() {
    super.loadView()

    self.view = LoginView(frame: CGRect.zero)
}

LoginView 类初始化两个标签并应设置一些约束。

class LoginView: UIView {

var usernameLabel: UILabel!
var passwordLabel: UILabel!


override init (frame : CGRect) {
    super.init(frame : frame)

    setupLabels()
}

convenience init () {
    self.init(frame:CGRect.zero)
}

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
}

private func setupLabels(){
    //Init labels and set a simple text
    self.usernameLabel = UILabel()
    self.usernameLabel.text = "Username"
    self.passwordLabel = UILabel()
    self.passwordLabel.text = "Password"

    //Set constraints which aren't possible since there is no contentView, perhaps using the frame?
    }
}

这是行不通的,因为视图的边界是 0。但是我找不到任何资源来深入了解这是否可能,所以我尝试了我的方法,但行不通。

如何将 UIViewController 的视图设置为以编程方式创建的自定义 UIView?或者上面的片段是推荐的吗?

这是基于 Jadar 答案的工作解决方案:

class LoginViewController: UIViewController {

    override func loadView() {
        view = LoginView()
    }

    override func viewDidLoad() {
        super.viewDidLoad()        
    //  Do any additional setup after loading the view.

    }
}

class LoginView: UIView {

var usernameLabel: UILabel!
var passwordLabel: UILabel!

override init(frame: CGRect) {
    super.init(frame: frame)

    self.usernameLabel = UILabel()
    self.usernameLabel.text = "Username"
    self.passwordLabel = UILabel()
    self.passwordLabel.text = "Password"

    addSubview(usernameLabel)
    addSubview(passwordLabel)

    if let superview = usernameLabel.superview{
        //Setting AutoLayout using SnapKit framework
        usernameLabel.snp.makeConstraints { (make) in
            make.center.equalTo(superview)
        }
    }
}

Result:


看起来这里确实有两个问题。第一,以编程方式设置 ViewController 的最佳方法是什么。另一个是如何以编程方式设置视图。

首先,让 ViewController 以编程方式使用不同的 UIView 子类的最佳方法是在loadView方法。根据苹果的docs https://developer.apple.com/reference/uikit/uiviewcontroller/1621454-loadview:

您可以重写此方法以手动创建视图。 如果您选择这样做,请将视图层次结构的根视图分配给 视图属性。您创建的视图应该是唯一的实例并且 不应与任何其他视图控制器对象共享。你的 此方法的自定义实现不应调用 super。

这看起来像这样:

class LoginViewController: UIViewController {    
    override func loadView() {
        // Do not call super!
        view = LoginView()
    }
}

这样你就不必处理它的大小问题,因为视图控制器本身应该处理它(就像它处理它自己的 UIView 一样)。

记住,不要打电话super.loadView()否则控制器会感到困惑。另外,我第一次尝试这个时,我遇到了黑屏,因为我忘记打电话window.makeKeyAndVisible()在我的应用程序代理中。在这种情况下,视图甚至从未添加到窗口层次结构中。您始终可以使用 Xcode 中的“查看内省器”按钮来查看发生了什么。

其次,您需要致电self.addSubview(_:)在你的 UIView 子类中以便让它们出现。将它们添加为子视图后,您可以使用以下命令添加约束NSLayoutConstraint.

private func setupLabels(){
    // Initialize labels and set their text
    usernameLabel = UILabel()
    usernameLabel.text = "Username"
    usernameLabel.translatesAutoresizingMaskIntoConstraints = false // Necessary because this view wasn't instantiated by IB
    addSubview(usernameLabel)

    passwordLabel = UILabel()
    passwordLabel.text = "Password"
    passwordLabel.translatesAutoresizingMaskIntoConstraints = false // Necessary because this view wasn't instantiated by IB
    addSubview(passwordLabel)

    NSLayoutConstraint.activate(NSLayoutConstraint.constraints(withVisualFormat: "V:|-10-[view]", options: [], metrics: nil, views: ["view":usernameLabel]))
    NSLayoutConstraint.activate(NSLayoutConstraint.constraints(withVisualFormat: "V:|-20-[view]", options: [], metrics: nil, views: ["view":passwordLabel]))

    NSLayoutConstraint.activate(NSLayoutConstraint.constraints(withVisualFormat: "H:|-10-[view]", options: [], metrics: nil, views: ["view":usernameLabel]))
    NSLayoutConstraint.activate(NSLayoutConstraint.constraints(withVisualFormat: "H:|-20-[view]", options: [], metrics: nil, views: ["view":passwordLabel]))
}

有关用于创建约束的视觉格式语言的更多信息,请参阅视觉FL指南 https://developer.apple.com/library/content/documentation/UserExperience/Conceptual/AutolayoutPG/VisualFormatLanguage.html#//apple_ref/doc/uid/TP40010853-CH27-SW1

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

将 UIViewController 视图属性设置为没有故事板/笔尖的自定义 UIView 类 的相关文章

随机推荐