Swift Tips 007 - Using `#function` for UserDefaults key consistency
每天了解一点不一样的 Swift 小知识
代码截图
小笔记
这段代码在说什么
这段代码为 UserDefaults 进行了扩展,并为其增加了一个名称为 onboardingCompleted,类型为 BOOL 的计算属性,用于获取 UserDefaults 里是键名为 onboardingCompleted 的值
#function
是什么
#function
是 Swift 编译器为我们提供的一个编译符号,它的作用是描述包含这个符号的方法名称,除了 #function
,以外常用的几个编译符号还有 #column
,#line
,#file
。
符号 | 类型 | 描述 |
---|---|---|
#file | String | 包含这个符号的文件的路径 |
#line | Int | 符号出现处的行号 |
#column | Int | 符号出现处的列 |
#function | String | 包含这个符号的方法名字 |
在 Swift 3.0 之前,
#function
的写法是__FUNCTION__
这些编译符号怎么用?
可以简单的将这些编译符号理解为一个变量,所以怎么使用变量就怎么使用这些编译符号吧。
代码截图里展示了如果在方法里面使用编译符号,下面的代码将展示如何在方法定义里使用编译符号。
这里假设我们要打印出某个方法的相关信息,例如它所在的文件名称,调用方名称,当前行数等。
func printLog<T>(message: T,
file: String = #file,
method: String = #function,
line: Int = #line)
{
print("\((file as NSString).lastPathComponent)[\(line)], \(method): \(message)")
}
那么它的输出结果就会是这样的
// Test.swift
func method() {
//...
printLog("这是一条输出")
//...
}
// 输出:
// Test.swift[62], method(): 这是一条输出
这样做的好处是什么
说好处之前,我们先想想,如果不用 #function
的话,我们会怎样从 UserDefaults 里取 key 值呢?八成你的代码会如下所示:
extension UserDefaults {
var onboardingCompleted: Bool {
get { return bool(forKey:"onboardingCompleted") }
set { set(newValue, forKey: "onboardingCompleted") }
}
}
在这种状况下,我们要自己手动保证 getter
和 setter
里面 key 值的一致,这就增加了出错的概率。
通过图片里的方式,即使用 #function
作为 key 的话,就很好的保证了 getter
和 setter
里 key 值的一致问题,我们只需要关心方法名是否为我们需要的 key 即可。