我创建了一些示例项目,以测试各种类型的变量实现,以测试仅执行一次,每次执行一次的变量
class Something:NSObject
{
var clock:Int = 0
override var description: String
{
let desc = super.description
clock += 1
return "\(desc) Clock: \(clock)"
}
}
static var staticVar:Something
{
print("static Var")
return Something()
}
static var staticVar2:Something = {
print("static Var II")
return Something()
}()
lazy var lazyVar:Something = {
print("lazy Var")
return Something()
}()
var simpleVar:Something {
print("simple Var")
return Something()
}
var simpleVar2:Something = {
print("simple Var II")
return Something()
}()
然后在viewDidLoad()
中(以确保变量已被初始化),调用所有var几次并保存在数组中以保持强引用
var strongArr = [Something]()
print("== STATIC VAR")
strongArr.append(ViewController.staticVar)
print(strongArr.last!.description)
strongArr.append(ViewController.staticVar)
print(strongArr.last!.description)
strongArr.append(ViewController.staticVar)
print(strongArr.last!.description)
print("\n== STATIC VAR {}()")
strongArr.append(ViewController.staticVar2)
print(strongArr.last!.description)
strongArr.append(ViewController.staticVar2)
print(strongArr.last!.description)
strongArr.append(ViewController.staticVar2)
print(strongArr.last!.description)
print("\n== SIMPLE VAR")
strongArr.append(self.simpleVar)
print(strongArr.last!.description)
strongArr.append(self.simpleVar)
print(strongArr.last!.description)
strongArr.append(self.simpleVar)
print(strongArr.last!.description)
print("\n== SIMPLE VAR {}()")
strongArr.append(self.simpleVar2)
print(strongArr.last!.description)
strongArr.append(self.simpleVar2)
print(strongArr.last!.description)
strongArr.append(self.simpleVar2)
print(strongArr.last!.description)
print("\n== LAZY VAR {}()")
strongArr.append(self.lazyVar)
print(strongArr.last!.description)
strongArr.append(self.lazyVar)
print(strongArr.last!.description)
strongArr.append(self.lazyVar)
print(strongArr.last!.description)
这是在控制台中注销的结果
== STATIC VAR
static Var
<_TtCC8DemoDemo14ViewController9Something: 0x600003725100> Clock: 1
static Var
<_TtCC8DemoDemo14ViewController9Something: 0x600003725160> Clock: 1
static Var
<_TtCC8DemoDemo14ViewController9Something: 0x600003725270> Clock: 1
== STATIC VAR {}()
static Var II
<_TtCC8DemoDemo14ViewController9Something: 0x6000037251b0> Clock: 1
<_TtCC8DemoDemo14ViewController9Something: 0x6000037251b0> Clock: 2
<_TtCC8DemoDemo14ViewController9Something: 0x6000037251b0> Clock: 3
== SIMPLE VAR
simple Var
<_TtCC8DemoDemo14ViewController9Something: 0x600003725240> Clock: 1
simple Var
<_TtCC8DemoDemo14ViewController9Something: 0x6000037252a0> Clock: 1
simple Var
<_TtCC8DemoDemo14ViewController9Something: 0x6000037252b0> Clock: 1
== SIMPLE VAR {}()
<_TtCC8DemoDemo14ViewController9Something: 0x600003738100> Clock: 1
<_TtCC8DemoDemo14ViewController9Something: 0x600003738100> Clock: 2
<_TtCC8DemoDemo14ViewController9Something: 0x600003738100> Clock: 3
== LAZY VAR {}()
lazy Var
<_TtCC8DemoDemo14ViewController9Something: 0x60000372ea70> Clock: 1
<_TtCC8DemoDemo14ViewController9Something: 0x60000372ea70> Clock: 2
<_TtCC8DemoDemo14ViewController9Something: 0x60000372ea70> Clock: 3
基于这些测试,如果两个变量都定义为闭包(最后为()
),则看起来懒变量和简单变量之间没有区别。
作为闭包的变量实现会自动使变量变懒还是我缺少什么?
答案 0 :(得分:1)
区别在于运行变量的初始化代码的时间。对于.order_by(F('round_date').desc(nulls_last=True))
vars,初始化代码在该变量的首次访问时运行。对于implementation 'com.gdacciaro:iosdialog:1.0.3'
var,它是在初始化struct / class时运行的。
lazy
输出:
non-lazy
请注意如何首先初始化非延迟struct N {
lazy var a: Int = { print("Setting A"); return 5}();
var b: Int = { print("Setting B"); return 5 }()
}
var n = N()
print(n.a)
print(n.b)
。 Setting B
Setting A
5
5
仅在访问时初始化。无论哪种情况,每个属性的初始化程序仅运行一次。
答案 1 :(得分:1)
当您将它们与struct /类的其他属性混合使用时,它们会变得更加有趣。这是我想到的几个:
struct Person {
var firstName: String
var lastName: String
lazy var fullName1 = "\(firstName) \(lastName)" // OK
var fullName2: String = { "\(firstName) \(lastName)" }() // invalid
init(firstName: String, lastName: String) {
self.firstName = firstName
self.lastName = lastName
}
}
原因是在初始化期间对var-as-closure进行了评估,而Swift不保证将首先初始化哪个属性。初始化firstName
时,lastName
和fullName2
可能尚未初始化。
let p = Person(firstName: "John", lastName: "Smith")
print(p.fullName1) // runtime error
您第一次读lazy var
时会计算得出,因此根据定义,它会改变结构。因此let p = Person(...)
是无效的。您必须使用var p = Person(...)
。
但是,如果Person
是一个类,则可以使用let p = Person(...)
,因为这里的“ constant”表示p
指向固定的内存地址,但是该地址处的对象可以随时更改