全局变量/常量如何在 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 中变得懒惰的主要内容,如果未能解决你的问题,请参考以下文章

如何定义常量在全局范围内nodejs

php 类中定义全局变量|php类定义变量|php类定义常量

Swift-Swift中的全局变量和函数的创建

solidity:1. 变量和常量

mfc怎么设置全局变量

Objective-C和Swift实现单例的几种方式