如何获取方法定义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
的全局“根”记录器(首字母大写)。这使得可能不想命名自己的函数(例如顶级函数或闭包)更容易。
我正在使用以下内容来记录一些函数调用。
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
的全局“根”记录器(首字母大写)。这使得可能不想命名自己的函数(例如顶级函数或闭包)更容易。