在 Swift 中,为什么分配给静态变量也会调用它的 getter

2023-11-25

我知道在 Swift 中,静态变量是隐式惰性的:https://stackoverflow.com/a/34667272/1672161

但我不清楚为什么会发生这种情况:

protocol HatType {}

class Hat: HatType {
    init() { print("real hat") }
}

class MockHat: HatType {
    init() { print("mock hat") }
}

struct HatInjector {
    static var hat: HatType = Hat()
}

HatInjector.hat = MockHat()

// Output:
// real hat
// mock hat

我看到的是,对静态变量的赋值在某种意义上也调用了 getter。这对我来说并不直观。这里发生了什么?为什么任务不只发生?


这是因为静态和全局存储变量当前是(这是all可能会发生变化)编译器仅给出一个访问器 –unsafeMutableAddressor,它获取指向变量存储的指针(这可以看出通过检查发出的 SIL 或 IR).

该访问器:

  1. 获取指向编译器生成的全局标志的指针,确定静态变量是否已初始化。

  2. Calls swift_once使用此指针以及初始化静态变量的函数(这是您给它的初始化表达式,即= Hat())。在苹果平台上,swift_once simply 转发到dispatch_once_f.

  3. 返回指向静态变量存储的指针,调用者可以自由读取和更改该指针,因为存储具有静态生命周期。

所以它或多或少相当于 Objective-C 线程安全的延迟初始化模式:

+(Hat*) hat {

    static Hat* sharedHat = nil;
    static dispatch_once_t oncePredicate;

    dispatch_once(&oncePredicate, ^{
        sharedHat = [[Hat alloc] init];
    });

    return sharedHat;
}

主要区别在于 Swift 返回一个指向存储的指针sharedHat(指向引用的指针),而不是sharedHat itself(只是对实例的引用)。

因为这就是那一个and only静态和全局存储变量的访问器,为了执行赋值,Swift 需要调用它来获取指向存储的指针。因此,如果它尚未初始化 - 访问器需要在调用者之前首先将其初始化为其默认值(因为它不知道调用者将用它做什么)then将其设置为另一个值。

这种行为确实有些不直观,并且已经被归档为错误。正如乔丹·罗斯在报告评论中所说:

目前这是设计使然,但可能值得更改设计。

因此,这种行为很可能会在该语言的未来版本中发生变化。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 Swift 中,为什么分配给静态变量也会调用它的 getter 的相关文章

  • SwiftUI 导航:如何将详细信息视图切换到不同的项目?

    我正在努力实现以下导航行为 用户可以从列表中选择一个项目 该项目会触发该项目的详细信息视图 在此详细视图上 导航栏中有一个 添加 按钮 可打开用于添加其他项目的模式表 到目前为止 一切都按预期进行 但添加项目后 我希望详细视图显示新项目 我
  • 领域列表未存储在 Swift 4.2 的发布配置中

    我刚刚构建了我的应用程序的最新版本 并且遇到了一个问题List我的所有领域对象上的 s 都没有被存储 这是一些示例代码 Object public class ReportItem Object objc dynamic var id St
  • 如何在 Swift 中退出“DispatchQueue.main.asyncAfter”

    我想在调用 deinit 时退出 DispatchQueue main asyncAfter 子视图 swift DispatchQueue main asyncAfter deadline now 5 0 self doSomething
  • 切换到 Xcode 7 后,应用程序大小从 9 MB 增长到 60 MB,有解决办法吗?

    我一直在回顾 Git 历史来寻找文件大小发生巨大变化的原因 但我能找到的唯一真正原因是从 Xcode 6 切换到 Xcode 7 GM 我发现这些是文件大小贡献最大的 10 个 ipa创建自Archive操作在一个Release构建配置 u
  • Alamofire 仅在 GET 请求上出现请求错误

    我正在努力将我的项目从 AFNetworking 转移到 Alamofire 真的很喜欢这个项目 POST 请求工作得很好 但是 我在尝试发出 GET 请求时收到此错误 这是一些示例代码 class func listCloudCrednt
  • 保存下拉列表中的值

    这是我的情况 我有 2 页 一页用于选择值 一页用于编辑与该值关联的数据库相关内容 现在 我对如何将从下拉列表中选择的值保存到 PHP 的变量中一无所知 并且已经进行了相当多的研究 有任何想法吗 HTML
  • 为什么java(>=7版本)不支持运行没有main方法的程序? [关闭]

    Closed 这个问题是无法重现或由拼写错误引起 help closed questions 目前不接受答案 class WithoutMain static System out println Without main class Sy
  • 以编程方式进行排序时检索 ViewController 堆栈

    static func showMenuView parentVC UIViewController let storyboard UIStoryboard name Main bundle nil let resultController
  • 有没有办法重置特定类的所有静态属性?

    您可能知道 静态属性使测试变得困难 有没有办法将特定类的所有静态属性重置回其初始状态 理想情况下 这不需要为每个类定制代码 但可以通过继承以通用方式使用 或者完全从类外部使用 请不要回复 不要使用静态属性 之类的内容 谢谢 假设您正在使用
  • Swift 中 UIViewController 子类成员的双重初始化

    我想制作一个自定义容器视图控制器并向其子类添加一些成员UIViewController 当我尝试使用以下代码从应用程序委托初始化它时 self window UIWindow frame UIScreen mainScreen bounds
  • 搜索TableView无法选择行

    在搜索 tableView 时 每次我尝试选择一行时 它都会返回到未搜索的 tableView 我缺少什么 当不过滤表格时 segue 工作得很好 当搜索栏被激活时 选择行的能力就会消失 import UIKit import Founda
  • 如何修复C风格的for语句?

    什么是正确的修复方法C 风格的 for 语句对于下面发布的代码 目前我正在交战 C 风格的 for 语句已弃用 并将在将来删除 斯威夫特的版本 var ifaddr UnsafeMutablePointer
  • Django 1.6 的静态文件

    我花了一整天但没有任何作用 我在这里看到了至少 20 篇关于同一主题的帖子 它们各不相同 有不同的建议 但没有一个对我有用 使用 Python 2 7 运行 Django 1 6 我正在尝试从 django 教程加载民意调查应用程序的 cs
  • Swift 3 '[UIApplicationLaunchOptionsKey:任意]?'无法转换为 '[String : NSString]'

    我有一个 TVOS 应用程序已从 Swift 2 转换为 Swift 3 但出现以下错误 我不确定如何让它安静下来 UIApplicationLaunchOptionsKey 任意 无法转换为 String NSString 它出现在这段代
  • 在 Swift 中将 Int 转换为 UInt32

    我正在制作一个 Tcp 客户端 因此使用CFStreamCreatePairWithSocketToHost它期望第二个参数为 UInt32 这是我正在尝试做的事情的示例 func initNetwork IP String Port In
  • iOS 内存警告

    我正在尝试使用从 Parse 数据库下载的图像填充集合视图 但我收到内存警告 然后偶尔崩溃 有谁知道其他应用程序如何设法呈现这么多图像而不崩溃 有人可以告诉我如何优化我已有的东西吗 这是所有相关代码 https gist github co
  • 打印附加结构(swift 4)

    我有三个 textifled 用于将数据附加到结构中 如何打印我附加的内容 现在我收到一条错误消息 import UIKit class ViewController UIViewController IBOutlet var c UITe
  • 具有多种自定义单元格类型的 RxSwift 表视图

    我想知道是否有任何代码示例RxSwift当我可以在一个表视图中使用多个自定义单元格时 例如 我有两个部分 第一部分有 10 个单元格 类型为CellWithImage标识符和第二部分有 10 个带有类型的单元格CellWithVideo标识
  • 初始化变量的不同方式

    在 C 中初始化变量有多种方法 int z 3 与 int 相同z 3 Is int z z 3 same as int z z 3 您可以使用 int z z 3 Or just int z 3 Or int z 3 Or int z i
  • 当设置 setVisibleXRangeMaximum 时,iOS-Charts X 轴值无限重复

    我正在尝试绘制一个图表 其中 x 轴是TimeIntervalY 轴是power consumption 由于每天都会有数据 因此将有太多数据无法显示 因此 我想一次显示 5 个值 我通过设置实现了这一点self chart setVisi

随机推荐

  • 在 Hadoop 2 上运行作业时无法初始化集群异常

    该问题与我之前的问题相关所有守护进程都在运行 jps 显示 6663 JobHistoryServer 7213 ResourceManager 9235 Jps 6289 DataNode 6200 NameNode 7420 NodeM
  • 数据库如何在B-Tree/B+Tree内部存储数据

    我的问题是数据库如何存储数据以及如何在内部执行查询 假设我们的表中有以下字段 ID Name Age Weight Manager 我们查询select from Table1 where age gt 50 and weight lt 1
  • 转储进程的内存

    当读取 proc PID maps 时 您将获得映射的内存区域 有没有办法转储这个区域之一 cat proc 18448 maps snip 0059e000 005b1000 r xp 00000000 08 11 40 usr loca
  • Django:选择具有最大时间戳的值或连接到同一个表

    我有一个简单的 Django 模型 class Server models Model name models CharField max length 120 class ServerPropertie models Model name
  • 数组中的前增量与后增量

    我正在学习编程 我是从C语言开始的 我正在读 Let us C 书 我在那本书中经历了这个程序 main int a 5 5 1 15 20 25 int i j k 1 m i a 1 j a 1 m a i printf n d d d
  • Gnuplot 平滑置信区间线而不是误差线

    我想要在数据线上方和下方有 95 的置信区间线 而不是每个点的垂直条 有没有一种方法可以在 gnuplot 中执行此操作而无需绘制另一条线 或者我是否需要绘制另一条线 然后对其进行适当的标记 您可以使用filledcurves风格填充区域9
  • Google Colab 上的 PyTorch Geometric CUDA 安装问题

    我正在开发一个 PyTorch Geometric 项目 使用 Google Colab 来支持 CUDA 由于默认情况下它的库不存在 因此我运行 pip install upgrade torch scatter pip install
  • ASP.NET WEB API 未绑定到 POST 上的动态对象

    如果有以下 Api 控制器 使用 StrutureMap 进行 DI using System using System Dynamic using System Net using System Net Http using System
  • python pandas:从财政年度和月份获取财政季度(针对英国)

    我有一个数据框 其中有两个有用的列 1 财政年度 2 日期 我想添加一个显示财政季度的新列 仅供参考 英国财政年度为 4 月 1 日至 3 月 31 日 我的数据如下所示 fiscal year date FY15 16 2015 11 0
  • 如何使用 HTTP 将 CORS 规则添加到 Azure 存储模拟器?

    要使用 Azure 存储 模拟器 表服务 我需要为我的 TypeScript 浏览器应用程序添加 CORS 规则 我想使用 REST 接口 来自 Postman 而不是具有同源策略的浏览器 手动添加该规则 该文档没有给出模拟器的正确 URL
  • 为什么 IIS 比 ASP.NET 开发服务器慢?

    我有一个 ASPX 网页 它执行一些复杂的操作和数据库调用 当我通过运行 ASP NET Development Server Cassini 查看网页时 大约需要200ms Then 无需更改任何代码和配置 我将网站部署到本地计算机 II
  • Java FX 2 警报声音

    如何在 Java FX 2 中播放警报声音 有没有办法使用操作系统默认通知声音 使用纯 JavaFX 播放声音 只需使用一个实例AudioClip 这非常适合仅演奏单个短音 播放默认通知声音 关于 Windows 操作系统 有一种方法可以通
  • 自定义首选项 Android Kotlin

    我想子类化Preference在 Kotlin 中创建自定义首选项 我无法在 首选项 屏幕中获取要膨胀的自定义首选项 如果我从我的首选项屏幕中删除此自定义首选项 我已实现的其余首选项 此处未显示 工作正常 类似的还有很多seeming这里有
  • Google Maps JS API v3 - 简单的多标记示例

    Google Maps Api 相当新 我有一组数据想要循环浏览并绘制在地图上 看起来相当简单 但我发现的所有多标记教程都相当复杂 让我们使用 Google 网站上的数据数组作为示例 var locations Bondi Beach 33
  • Cloud Endpoint 参数不应命名

    我想发送一个HashMap
  • 跨域获取iframe当前src url [重复]

    这个问题在这里已经有答案了 我的网络应用程序中有一个 iframe 我需要从父文档获取其当前 url 当用户导航框架并更改原始源 url 时 只需要 URL 即可进行社交分享 作为跨域场景 我不拥有子文档 它是远程域 我知道同源策略可以防止
  • 在 UIWebView 中启用 Cookie

    如何在使用 UIWebView 窗口的 iPhone 应用程序中启用 cookie 以便我的登录系统正常工作 肯定是从 NSHTTPCookieStorage sharedHTTPCookieStorage cookieAcceptPoli
  • 在一定时间后自动关闭窗口

    在一个类中 在一个函数中 我正在创建一个 Tkinter Canvas 该函数正在被另一个类调用 我希望 Tkinter 窗口弹出 30 秒 然后自行关闭 我有打电话 master mainloop time sleep 30 master
  • 如果字段值为空,如何告诉 Jackson 在序列化期间忽略该字段?

    如果该字段的值为空 如何将 Jackson 配置为在序列化期间忽略该字段值 例如 public class SomeClass what jackson annotation causes jackson to skip over this
  • 在 Swift 中,为什么分配给静态变量也会调用它的 getter

    我知道在 Swift 中 静态变量是隐式惰性的 https stackoverflow com a 34667272 1672161 但我不清楚为什么会发生这种情况 protocol HatType class Hat HatType in