为啥在 Swift 中使用惰性 var 初始化时添加框架不显示 UIView

Posted

技术标签:

【中文标题】为啥在 Swift 中使用惰性 var 初始化时添加框架不显示 UIView【英文标题】:Why adding frame doesn't show a UIView when initializing with lazy var in Swift为什么在 Swift 中使用惰性 var 初始化时添加框架不显示 UIView 【发布时间】:2021-10-18 05:06:07 【问题描述】:

我正在开发一个 Swift 项目,但我不清楚以编程方式制作 UI 的一件事。 我尝试在屏幕上显示一个简单的 UIView。

lazy var container: UIView = 
    let view = UIView(frame: CGRect(x: 0, y: 0, width: 30, height: 30))
    view.backgroundColor = UIColor.systemImageGray()
    view.layer.cornerRadius = view.layer.bounds.width / 2
    view.clipsToBounds = true
    return view
()

override func viewDidLoad() 
    super.viewDidLoad()
    view.addSubview(container)
    setupConstraints()


func setupConstraints() 
    container.translatesAutoresizingMaskIntoConstraints = false
    NSLayoutConstraint.activate([
        container.topAnchor.constraint(equalTo: self.topAnchor, constant: 14),
        container.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -14),
        container.widthAnchor.constraint(equalToConstant: 30),
        container.heightAnchor.constraint(equalToConstant: 30)
    ])

上面的代码运行正常,但是由于我设置了两次with和height,感觉是多余的,比如UIView(frame: CGRect(x: 0, y: 0, width: 30, height: 30))在setupConstraints中设置宽高约束。

由于我在UIView的frame中设置了宽度和高度,我以为我不需要在setupConstraints中设置宽度和高度约束,但是除非我再次添加宽度和高度约束,否则它不会显示视图。所以在这种情况下,为什么我不能在 UIView(frame: CGRect(x: 0, y: 0, width: 30, height: 30)) 中设置宽度和高度,而且我还必须再次添加宽度/高度约束?

【问题讨论】:

【参考方案1】:

frame 在您不使用自动布局引擎放置视图时很有用。

当你这样做时:

container.translatesAutoresizingMaskIntoConstraints = false

您明确告诉引擎忽略框架并且您负责应用一组新的约束。

因此你最终会这样做:

NSLayoutConstraint.activate([
    container.topAnchor.constraint(equalTo: self.topAnchor, constant: 14),
    container.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -14),
    container.widthAnchor.constraint(equalToConstant: 30),
    container.heightAnchor.constraint(equalToConstant: 30)
])

根据 Autolayout 的预期设置定位和动态大小。


translatesAutoresizingMaskIntoConstraints

一个布尔值,用于确定视图的自动调整掩码是否 被翻译成 Auto Layout 约束。

参考:https://developer.apple.com/documentation/uikit/uiview/1622572-translatesautoresizingmaskintoco

【讨论】:

非常感谢您的快速回复!现在我明白为什么它不起作用了。是的,起初,我厌倦了 let view = UIView(),但是,它不会使视图变成圆形,因为我在该代码之后立即调整角半径( view.layer.cornerRadius = view.layer.bounds.宽度 / 2)。当我使用 let view = UIView() 时,还有其他方法可以添加圆角半径吗?我想我可以使用 viewdidlayoutsubviews 或其他东西,但我会将我的项目作为 MVC 模式,所以如果可能的话,我想将角半径的东西放在惰性 var 属性中。 @Yuuu Aah,我没有注意到您有 layer.cornerRadius 修改。在这种情况下,如果您知道高度和宽度是恒定的,那么到目前为止您通过提供框架所做的一切都很好。但是如果高度和宽度是动态的,那么我会把它放在layoutSubviews 中。 Also see this

以上是关于为啥在 Swift 中使用惰性 var 初始化时添加框架不显示 UIView的主要内容,如果未能解决你的问题,请参考以下文章

Swift: let 未初始化,但 var 已初始化。为啥? [复制]

为啥每个线程多次初始化惰性变量

为啥在 Swift 中使用“let”而不是 var?

Swift 常量默认是惰性的吗?

Swift 中的惰性属性相当于 Objective C 中的惰性 Init getter

全局变量/常量如何在 swift 中变得懒惰