使用此代码:
func externalFunc() {
println("How can I know which object/class is calling me?")
}
class Test {
func callExternalFunc() {
externalFunc()
}
}
在Objective-C运行时objc_msgSend
passes two hidden parameters中我们发送的每条消息。他们是自我和 _cmd 。 (Source)
在上面的示例中,有没有办法知道谁在调用externalFunc
?
答案 0 :(得分:17)
我不确定是否有办法自动获取此信息,但如果您向函数添加String类型的默认参数并将其设置为#function
,则可以获取此信息。
例如......
func externalFunc(callingFunctionName: String = #function) {
println("Calling Function: \(callingFunctionName)")
}
然后你可以在没有添加默认参数的情况下调用它...
let test = Test()
test.callExternalFunc()
它将打印以下内容......
"Calling Function: callExternalFunc()"
答案 1 :(得分:7)
如果您愿意修改方法签名,可以执行以下操作:
func externalFunc(file: String = #file, line: Int = #line) {
println("calling File:\(file) from Line:\(line)")
}
来自apple的swift blog
Swift借用D语言的一个聪明的功能:这些标识符 (__FILE__& __LINE__)扩展到调用者的位置 在默认参数列表中进行评估。
请注意, __ FILE __ 和 __ LINE __ 已在Swift 2.2中弃用,并已在Swift 3中删除。它们被 #file 取代,和 #line 。
答案 2 :(得分:1)
这是我在github上找到的一个很棒的实用工具类:
https://github.com/nurun/swiftcallstacktrace
像这样使用:
let callingMethodInfo = CallStackAnalyser.getCallingClassAndMethodInScope(false)
if let callingMethodInfo = callingMethodInfo {
NSLog("class: %@", callingMethodInfo.0)
NSLog("method: %@", callingMethodInfo.1)
}
答案 3 :(得分:-1)
在您的问题中,您提到了self
和_cmd
。
self
(这是合乎逻辑的)。
_cmd
(当前方法的选择器)无法访问。没有理由可以访问它,Swift没有在Obj-C上下文之外使用选择器(在纯Swift中你不能动态调用选择器)。唯一的用例是打印当前函数的名称以进行调试。使用__FUNCTION__
宏可以在Obj-C(或C)中实现相同的效果。在Swift中也可以实现同样的目标:
func getCurrentFunctionName(functionName: StaticString = #function) -> String {
return String(functionName)
}
func externalFunc() {
print("Function name: \(getCurrentFunctionName())") // prints "externalFunc"
}
请注意,在您的示例中,externalFunc
是函数,而不是方法。即使在Obj-C中,self
或_cmd
也不可用。
如果你想知道谁调用了你的方法(我真的认为你想知道它用于调试目的),那么你可以检查你的调用栈:
func externalFunc() {
let stackSymbols = NSThread.callStackSymbols()
stackSymbols.forEach {
let components = $0.stringByReplacingOccurrencesOfString(
"\\s+",
withString: " ",
options: .RegularExpressionSearch,
range: nil
).componentsSeparatedByString(" ")
let name = components[3]
let demangledName = _stdlib_demangleName(name)
print("\(demangledName)")
}
}
打印(对于我的项目名为SwiftTest
):
SwiftTest.externalFunc () -> ()
SwiftTest.Test.callExternalFunc () -> ()
main
start
0x0