最近和同事在 Swift 中调用 ObjC 运行时方法的时候提起了 #function
这个字面量表达式。
然而,我发现大家好像对于这个字面量表达式的理解并不全面,当然也包括我自己。
查看了官方文档后,发现其含义可以概括为:
The name of the declaration in which it appears.
后续还有一段详细的解释:
Inside a function, the value of #function is the name of that function, inside a method it is the name of that method, inside a property getter or setter it is the name of that property, inside special members like init or subscript it is the name of that keyword, and at the top level of a file it is the name of the current module.
然而,我在看完之后还是想实际输出这些值,以确认自己的理解是到位的。
所以,现在就来总结一下 #function
这个字面量表达式的含义以及用法。
print(#function, #line) // TestFunction
当前项目/模块的名称是 TestFunction
,此时 #function
确实是模块的名称。
var testVar: Int {
get {
print(#function, #line) // testVar
return 0
}
set {
print(#function, #line) // testVar
}
}
let value = testVar
testVar = 1
可以看到,此时 #function
是该变量的名称。
class TestClass {
var testVar: Int {
get {
print(#function, #line) // testVar
return 0
}
set {
print(#function, #line) // testVar
}
}
}
let value1 = cls.testVar
cls.testVar = value1
可以看到,此时 #function
是该属性的名称。
func testFunction(arg: Int) {
print(#function, #line) // testFunction(arg:)
}
testFunction(arg: 1)
func testFunction1(_ arg: Int) {
print(#function, #line) // testFunction1(_:)
}
testFunction1(1)
可以看到,此时 #function
是该方法的名称。请注意 testFunction
和 testFunction1
的区别,前者有参数标签,而后者省略了参数标签。所以,#function
输出的值也不同。
func testFunction2(functionName: String = #function) {
print(functionName, #line) // TestFunction
}
testFunction2()
可以看到,此时 #function
是模块的名称(testFunction2()
是在当前文件的最顶层调用的)。
class TestClass {
init(value: Int) {
testVar = value
print(#function, #line) // init()
}
subscript(index: Int) -> Self {
print(#function, #line) // subscript(_:)
return self
}
func testFunction(arg: Int) {
print(#function, #line) // testFunction(arg:)
}
}
let cls = TestClass()
_ = cls[0]
cls.testFunction(arg: 1)
可以看到,此时 #function
是该方法的名称。
但是,请注意 subscript(index: Int) -> Self
中的 #function
并没有 index
参数标签,这一点和普通的函数/方法有所区别。
可能有朋友会将 #function
作为一些 ObjC 方法的参数。此时,大家一定要小心!
通过上图,我们可以发现 #function
其实是有具体类型的,而且它的类型是 String
。
这也可以解释为何 #function
可以作为 func testFunction2(functionName: String = #function)
中的默认参数。
那么,这会有什么问题呢?
我们知道,Swift 中的很多基础类型都是值类型(Int, Float, Double, Bool, String, enum, struct, Array, Dictionary, Set)。String 是值类型。
所以,它和 NSString
有本质上的不同!因为 NSString
是引用类型,而且它的基类是 NSObject
。
大多数时候,编译器会帮我们自动桥接 String
和 NSString
。但是,我们一定要注意桥接是在何时发生的,桥接有没有可能并没有按我们预期的方式工作。
在使用 Swift 与 ObjC 进行混编时,编译器帮我们做了很多事情。这样,我们就可以专注于业务,而不是语言之间的细节。
然而,我们还是要当心可能存在的概念混淆,以及自动发生的桥接操作。
不得不说,bug 往往就在一念之间~ 😆
参考内容:
Swift - Expressions
觉得不错?点个赞呗~
本文链接:Swift 中的 #function 到底是什么?
转载声明:本站文章如无特别说明,皆为原创。转载请注明:Ficow Shen's Blog