如何获取方法定义class的名称?

How to get a method’s defining class’s name?

我正在使用以下内容来记录一些函数调用。

func functionWasCalled(file: String = #file, function: String = #function) {
    print("Function \(function) of file \(file) was called.")
}

当它的调用者是一个方法时,我希望 functionWasCalled 也打印调用者所属的 class 的 名称。即使该方法是静态的。而且我不想将任何显式参数传递给 functionWasCalled。我能做什么?

尝试以下操作:

String(describing: self)

点赞:

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

let f = Foo()

f.test()

输出:

Foo

对于 class 名称,您可以使用 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)
    }

我不相信你特别要求的是可能的。除了提供的 #-literals.

就是说,如果您稍微更改一下语法,就可以获得您想要的效果。

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。确保您的 Logger 是无状态的,因此可以按需创建它们。

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,您可以像这样添加额外的 Logger.init

public init(for staticCaller: Any.Type) {
    self.caller = "\(staticCaller)"
}

这将导致类型被评估为它们自身而不是它们的元类型。

如果您的记录器是有状态的或具有中央配置,或者在其他情况下可能会出现大量记录器的问题,您应该将有状态的“引擎”部分从该前端中分离出来。您还可以使 log 成为惰性变量,或者在 self 可用时在 init 中初始化它。

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