我想对Swift中的一些属性使用Lazy初始化。 我目前的代码如下:
lazy var fontSize : CGFloat = {
if (someCase) {
return CGFloat(30)
} else {
return CGFloat(17)
}
}()
事情是,一旦设置了fontSize,它将永远不会改变。 所以我想做这样的事情:
lazy let fontSize : CGFloat = {
if (someCase) {
return CGFloat(30)
} else {
return CGFloat(17)
}
}()
这是不可能的。
只有这样才有效:
let fontSize : CGFloat = {
if (someCase) {
return CGFloat(30)
} else {
return CGFloat(17)
}
}()
所以 - 我想要一个延迟加载但永远不会改变的属性。
这样做的正确方法是什么?使用let
并忘记懒惰的初始化?或者我应该使用lazy var
并忘记属性的恒定性质?
答案 0 :(得分:24)
这是Xcode 6.3 Beta / Swift 1.2 release notes的最新经文:
让常量推广到不再需要立即 初始化。新规则是必须使用常量 在使用之前初始化(如var),并且它可能只是 初始化:初始化后未重新分配或变异。
这样可以实现以下模式:
let x: SomeThing
if condition {
x = foo()
} else {
x = bar()
}
use(x)
以前需要使用var,即使没有 突变发生。 (16181314)
显然,你并不是唯一一个对此感到沮丧的人。
答案 1 :(得分:22)
Swift book has the following note:
您必须始终将惰性属性声明为变量(使用var关键字),因为在实例初始化完成之后,可能无法检索其初始值。常量属性在初始化完成之前必须始终具有值,因此不能声明为惰性。
这在实现语言的上下文中是有意义的,因为在对象的初始化完成之前计算所有常量存储的属性。这并不意味着let
的语义在与lazy
一起使用时可能已被更改,但尚未完成,因此var
仍然是lazy
的唯一选项在这一点上。
就你提出的两个选择而言,我会根据效率来决定:
var lazy
let
注意:我会进一步优化您的代码,将条件推送到CGFloat
初始值设定项:
let fontSize : CGFloat = CGFloat(someCase ? 30 : 17)
答案 2 :(得分:10)
正如dasblinkenlight指出的那样,懒惰属性应始终在Swift中声明为变量。但是,有可能将属性设置为只读,因此它只能从定义实体的源文件中进行变换。这是我可以定义“懒惰”的最接近的。
private(set) lazy var fontSize: CGFloat = {
if someCase {
return 30
} else {
return 17
}
}()
答案 3 :(得分:0)
您可以将Burritos用于惰性常量属性。该库为Swift 5.1提供了不同的属性包装器。通过将以下行添加到Podfile中,将其与CocoaPods一起安装:
pod 'Burritos'
使用此库,您可以替换
lazy var fontSize : CGFloat = {
if (someCase) {
return CGFloat(30)
} else {
return CGFloat(17)
}
}()
使用
@LazyConstant var fontSize : CGFloat = {
if (someCase) {
return CGFloat(30)
} else {
return CGFloat(17)
}
}()
然后self.fontSize = 20
导致编译错误。