全局变量/常量如何在 swift 中变得懒惰
Posted
技术标签:
【中文标题】全局变量/常量如何在 swift 中变得懒惰【英文标题】:How the global variable / constants are lazy in swift 【发布时间】:2020-07-30 03:01:11 【问题描述】:来自docs.swift.org
全局变量
全局常量和变量总是延迟计算,类似于延迟存储属性。与惰性存储属性不同,全局常量和变量不需要使用惰性修饰符进行标记。
类型属性
存储类型属性在首次访问时被延迟初始化。
所以我测试他们两个的惰性如下
import Foundation
import CoreFoundation
var s = Date()
struct Sam
static let s = Date()
print(Date())
Timer.scheduledTimer(withTimeInterval: 2.0, repeats: false, block: (t) in
print(Sam.s)
print(s)
exit(0)
)
CFRunLoopRun()
我没有在操场上运行它。来自forums.swift.org 的人建议不要在操场上运行它。
所以我将它存储在一个名为 main.swift
的文件中,然后使用 swift main.swift
运行它
输出如下
2020-04-16 18:23:48 +0000 2020-04-16 18:23:50 +0000 2020-04-16 18:23:48 +0000
所以类型属性延迟初始化,但全局变量没有延迟初始化。那么它实际上意味着全局变量/常量是惰性计算的。
提前致谢。
【问题讨论】:
你能解释一下你试图用 Timer 和 run loop 实现什么,以及它如何证明实例化对象的惰性? 稍后访问惰性属性。然后检查它实际上是什么值?最近的值或以前的值。检查计时器内的第一个打印,这是类型属性。 From doc 类型属性是惰性的,因此每当第一次访问时它都会启动。当我启动计时器时,我打印了一个日期,类型属性日期正好是两秒后(当我在两秒后访问它时)。希望你明白了。 【参考方案1】:根据您链接的论坛帖子,main.swift
的范围类似于 Swift Playground 的范围,在顶层声明的变量被视为局部变量而不是全局变量。
在您的示例中,s
是一个局部变量,因此它不会被延迟初始化。
创建一个新文件,并且只在那里声明s
(我更改了名称以便更清楚):
// otherFile.swift
import Foundation
let globalS = Date()
然后在你的主要:
// main.swift
import Foundation
struct S
static let classS = Date()
let localS = Date()
print("Reference date: \(Date())")
sleep(2)
print("Local var s date: \(localS)")
print("Global var s date: \(globalS)")
print("Class property date: \(S.classS)")
这应该打印如下内容:
Reference date: 2020-04-16 21:47:47 +0000
Local var s date: 2020-04-16 21:47:47 +0000
Global var s date: 2020-04-16 21:47:49 +0000
Class property date: 2020-04-16 21:47:49 +0000
本地变量与参考时间具有相同的时间,因此它被急切地初始化。静态变量和全局变量在两秒后,证明它们是在调用时延迟实例化的。
这演示了全局变量和局部变量之间的区别:main 的***范围是函数中的局部范围,而其他文件中的***范围是全局范围。
【讨论】:
以上是关于全局变量/常量如何在 swift 中变得懒惰的主要内容,如果未能解决你的问题,请参考以下文章