Swift 如何获得方法’;s定义类’;她叫什么名字?

Swift 如何获得方法’;s定义类’;她叫什么名字?,swift,static-methods,Swift,Static Methods,我使用下面的代码来记录一些函数调用 func functionWasCalled(file: String = #file, function: String = #function) { print("Function \(function) of file \(file) was called.") } 当它的调用者是一个方法时,我希望调用functionwas也打印调用者所属类的名称。即使该方法是静态的。我不想将任何显式参数传递给functionWasCall

我使用下面的代码来记录一些函数调用

func functionWasCalled(file: String = #file, function: String = #function) {
    print("Function \(function) of file \(file) was called.")
}
当它的调用者是一个方法时,我希望调用
functionwas
也打印调用者所属类的名称。即使该方法是静态的。我不想将任何显式参数传递给functionWasCalled。我能做什么?

尝试以下操作:

String(describing: self)
就像这里:

class Foo {
    func test () {
        print(String(describing: self))
    }
}

let f = Foo()

f.test()
输出:

Foo

对于类名,可以使用
self.classForCoder
,对于文件名,也可以使用
#fileID

    func functionWasCalled(file: String = #file, function: String = #function, fileID: String = #fileID, callClass: AnyObject?) {
        print("Function \(function) of file \(file) was called.")
        print("File id", fileID)
        print("Class is - ", callClass?.classForCoder ?? self.classForCoder)
    }

我不相信你具体要求的是可能的。据我所知,除了所提供的#-文本之外,无法在调用者的上下文中隐式地计算某些内容

也就是说,如果您稍微修改一下语法,就可以得到想要的效果

public class Logger {
    public let caller: String

    public init(for caller: Any) {
        self.caller = "\(type(of: caller))"
    }

    public func info(_ message: String, file: String = #file, line: Int = #line, function: String = #function) {
        print("Function \(function) of \(caller) in file \(file) was called.")
    }
}
现在,在使用记录器的对象中,它们只需要使用一致的名称创建自己的日志,如
log
。确保您的记录器是无状态的,这样就可以按需创建它们

class MyLoggingThing {
    var log: Logger { Logger(for: self) }

    func doSomething() {
        log.info("Let's do this")
    }
}

// Function doSomething() of MyLoggingThing in file MyPlayground.playground was called.
您可以通过扩展使这一点变得更好,并处理静态方法:

protocol Logging {}
extension Logging {
    static var log: Logger { Logger(for: self) }
    var log: Logger { Logger(for: self) }
}

class MyLoggingThing: Logging {
    static func doSomethingStatic() {
        log.info("Even static")
    }
    func doSomething() {
        log.info("Let's do this")
    }
}
请注意,静态方法将显示类型为
MyLoggingThing.type
。这是好是坏,取决于你想要什么。如果您不喜欢额外的
.Type
,可以添加额外的
记录器.init
,如下所示:

public init(for staticCaller: Any.Type) {
    self.caller = "\(staticCaller)"
}
这将导致类型作为其自身而不是其元类型进行计算

如果您的记录器是有状态的,或者具有中心配置,或者在许多记录器可能存在问题的其他情况下,您应该将有状态的“引擎”部分与此前端分离。当
self
可用时,您还可以将
log
设置为惰性变量,或者在
init
中对其进行初始化


在我的个人日志模块中,我还有一个名为
Log
(大写)的全局“root”记录器。这使得不想命名自己的函数(例如顶级函数或闭包)更容易.

您能告诉我如何使用我提供的函数吗?这里使用
self
很可能是不正确的,因为这个函数可能是在日志类或其他常见类中定义的。您想打印定义类名还是调用方类名?我相信会有一些混淆,人们会将其理解为打印调用
函数所属的类的名称。您可能需要更清楚地说明您指的是调用方的类型。(我觉得这很清楚,但显然让很多人感到困惑。)这是否回答了你的问题?我很确定这个问题没有你想要的解决方法。您可以读取Thread.callStackSymbols,但即使您实现了Demanling,它在非符号化(发布)构建中也不太可能有用。在ObjC中,这是通过预处理器宏实现的,但它们在Swift中不存在,并且除了提供的特定#-文本外,无法在调用站点计算默认值。@RobNapier谢谢。希望现在好多了。如果不是,请告诉我callClass是什么?它是调用此函数的类。我不想显式地传递任何参数。对不起,我应该说清楚的。我对问题进行了编辑以反映这一点。您是否尝试了
self.dynamicType
?我无法访问调用方的self。