UIKit Programmatically:帮助编写 UI 代码时的不同方法
UIKit Programmatically: Help on different approaches when writing UI Code
最近,我开始以编程方式学习 UIKit,并且我注意到编写和组织 UI 代码的不同方法。
第一个是,声明一个带有闭包的常量,它将立即执行并且returns某个UI元素。
示例(第一种方法):
let mainLabel: UILabel = {
let v = UILabel()
v.translatesAutoresizingMaskIntoConstraints = false
v.text = "dummy text..."
//...
return v
}()
第二个是,声明一个UI元素计算变量,它是一个return某个UI元素的只读变量。
示例(第二种方法):
var mainLabel: UILabel {
let v = UILabel()
v.translatesAutoresizingMaskIntoConstraints = false
v.text = "dummy text..."
//...
return v
}
第三个是,声明一个工厂函数来创建 UI 元素,return 它。
示例(第三种方法):
private func createMainLabel(with text:String) -> UILabel {
let v = UILabel()
v.translatesAutoresizingMaskIntoConstraints = false
v.text = text
//...
return v
}
现在,我假设第二个和第三个选项非常相似,每次都创建一个新的 UI 元素实例,而第一个方法只创建该元素一次。
但我想了解是否还有更多内容,为什么我要使用一个而不是另一个,什么才是最佳实践,还有,是否有更优选的方式来编写我没有提到的 UI 代码在吗?
第一个 是一种常见的方法,而且在我看来是一种非常好的方法。您需要了解的有关 UI 元素的所有信息都集中在一处。但请注意,如果您需要在那里引用 self,则需要将 UI 元素设为惰性变量,因为在所有属性(非惰性或可选属性)初始化之前,self 不可用。例如:
let text = "Hello"
lazy var mainLabel: UILabel = {
let v = UILabel()
v.translatesAutoresizingMaskIntoConstraints = false
v.text = self.text // <-- here
//...
return v
}()
第二个我觉得很奇怪。我想不出一个有用的场景。每次访问变量时,都会处理一个新副本。我认为这至少令人困惑。
第三个 在您事先不知道您将需要多少个 UI 元素实例时特别有用。
缺少的一种常见方法是这样的:
let mainLabel = UILabel()
let secondaryLabel = UILabel()
override func viewDidLoad() {
super.viewDidLoad()
mainLabel.translatesAutoresizingMaskIntoConstraints = false
mainLabel.text = "dummy text..."
secondaryLabel.translatesAutoresizingMaskIntoConstraints = false
secondaryLabel.text = "secondary dummy text ..."
// build view hierarchy
// set AutoLayout constraints
}
我认为您更喜欢第一种方法还是最后一种方法主要是个人喜好问题。最后一个可以更轻松地一目了然地查看所有属性,而无需滚动。如果您想了解有关某个 UI 元素的更多信息,您会在 viewDidLoad 方法(或您在那里调用的某些 setupView() 方法)中看到所有内容,包括其 AutoLayout 约束。
最近,我开始以编程方式学习 UIKit,并且我注意到编写和组织 UI 代码的不同方法。
第一个是,声明一个带有闭包的常量,它将立即执行并且returns某个UI元素。
示例(第一种方法):
let mainLabel: UILabel = {
let v = UILabel()
v.translatesAutoresizingMaskIntoConstraints = false
v.text = "dummy text..."
//...
return v
}()
第二个是,声明一个UI元素计算变量,它是一个return某个UI元素的只读变量。
示例(第二种方法):
var mainLabel: UILabel {
let v = UILabel()
v.translatesAutoresizingMaskIntoConstraints = false
v.text = "dummy text..."
//...
return v
}
第三个是,声明一个工厂函数来创建 UI 元素,return 它。
示例(第三种方法):
private func createMainLabel(with text:String) -> UILabel {
let v = UILabel()
v.translatesAutoresizingMaskIntoConstraints = false
v.text = text
//...
return v
}
现在,我假设第二个和第三个选项非常相似,每次都创建一个新的 UI 元素实例,而第一个方法只创建该元素一次。 但我想了解是否还有更多内容,为什么我要使用一个而不是另一个,什么才是最佳实践,还有,是否有更优选的方式来编写我没有提到的 UI 代码在吗?
第一个 是一种常见的方法,而且在我看来是一种非常好的方法。您需要了解的有关 UI 元素的所有信息都集中在一处。但请注意,如果您需要在那里引用 self,则需要将 UI 元素设为惰性变量,因为在所有属性(非惰性或可选属性)初始化之前,self 不可用。例如:
let text = "Hello"
lazy var mainLabel: UILabel = {
let v = UILabel()
v.translatesAutoresizingMaskIntoConstraints = false
v.text = self.text // <-- here
//...
return v
}()
第二个我觉得很奇怪。我想不出一个有用的场景。每次访问变量时,都会处理一个新副本。我认为这至少令人困惑。
第三个 在您事先不知道您将需要多少个 UI 元素实例时特别有用。
缺少的一种常见方法是这样的:
let mainLabel = UILabel()
let secondaryLabel = UILabel()
override func viewDidLoad() {
super.viewDidLoad()
mainLabel.translatesAutoresizingMaskIntoConstraints = false
mainLabel.text = "dummy text..."
secondaryLabel.translatesAutoresizingMaskIntoConstraints = false
secondaryLabel.text = "secondary dummy text ..."
// build view hierarchy
// set AutoLayout constraints
}
我认为您更喜欢第一种方法还是最后一种方法主要是个人喜好问题。最后一个可以更轻松地一目了然地查看所有属性,而无需滚动。如果您想了解有关某个 UI 元素的更多信息,您会在 viewDidLoad 方法(或您在那里调用的某些 setupView() 方法)中看到所有内容,包括其 AutoLayout 约束。