在示例代码中,我看到了两种不同样式的声明对象。一个优于另一个的优势是什么?
两者都被声明为
var btn: UIButton!
风格1:
btn = UIButton()
btn.translatesAutoresizingMaskIntoConstraints = false
btn.layer.borderColor = UIColor.blue.cgColor
btn.layer.borderWidth = 1
...
self.view.addSubview(btn)
样式2:
btn = {
let b = UIButton()
b.translatesAutoresizingMaskIntoConstraints = false
b.layer.borderColor = UIColor.blue.cgColor
b.layer.borderWidth = 1
...
return b
}()
self.view.addSubview(btn)
我目前看到的唯一优势是,当你有很多对象时,第二种风格使代码更清晰。你也可以在Xcode中折叠它们。还有其他优势吗?不是第二个版本"成本"运行时有更多资源? 哪个更好?
由于
答案 0 :(得分:3)
闭包初始化(你的第二个例子)有三大优点。
优势一:初始化let
结构。您的示例使用UIButton
,它是一个类 - 引用类型。如果我们将结构初始化为let
,我们就不能改变它。我们无法更改其任何设置者,也不能在将其初始化为mutating
声明后调用标记为let
的任何方法。闭包初始化允许我们在分配到let
- 声明的变量之前进行此设置。
优势二:范围。我们初始化的闭包有自己的范围。它可以从封闭范围中捕获变量,但在范围内声明的变量在其外部不可用。这意味着我们没有变量名称的冲突。这也意味着ARC可以在初始化完成时进行一些清理。
优势三:类/结构成员变量的内联初始化。我列出的前两个优点并不总是必要的,你通常可以解决它们。但是如果没有关闭初始化,如果你想在声明它的位置初始化你的按钮,你会遇到这样的事情:
class MyViewController: UIViewController {
var button = UIButton()
override func viewDidLoad() {
super.viewDidLoad()
// TODO: Set up button's properties
view.addSubview(button)
}
}
但是通过闭包初始化,我们可以在声明点设置所有设置。
class MyViewController: UIViewController {
var button: UIButton = {
let button = UIButton()
// TODO: Set up button
return button
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(button)
}
}
答案 1 :(得分:1)
这些差异在小例子中相当微不足道,但在更大,更复杂的软件中可能更为重要。
在第一个示例中,WARNING:root:Unable to find `/pages/{attach}images/blog/profile.jpg` or variations.
的状态暂时无效 - 直到所有属性分配完成。在第二个示例中,按钮在分配给btn
时完全构建。此外,第二个代码实际上是一个工厂方法,可以分成单独的类并进行参数化。如果正在创建许多类似的按钮,则很有用。
将构建按钮和其他控件的职责分离到专业类是朝着减少iOS应用程序中视图控制器的大小和复杂性迈出的重要一步。