我正在寻找使Swift.print
函数起作用的方法。覆盖它不是一种选择,因为如果使用Swift.print(:)
选择器无法识别标识符:
@objc class func printSwizzle() {
guard let instance = class_getInstanceMethod(self, #selector(print(separator:terminator:))),
let swizzleInstance = class_getInstanceMethod(self, #selector(swizzlePrint(separator:terminator:))) else { return }
method_exchangeImplementations(instance, swizzleInstance)
}
那有可能吗? obj-c
运行时功能令人毛骨悚然。
答案 0 :(得分:3)
方法混乱是一种Objective-C功能,使您可以在运行时交换方法的实现。为此,您需要一个@objc
继承的NSObject
对象。您需要一种方法。
Swift.print
不是一种方法。这是在Swift
模块中声明的函数。我们可以说这是全球性的,但并不是真正的全球性。它是在模块Swift
中定义的,该模块会自动导入到每个Swift代码中,因此您可以在没有Swift.
前缀的情况下使用它。
总而言之,没有办法使Swift.print
陷入混乱。
您可以做的是使用自己的实现隐藏该函数,也就是说,如果您在自己的模块中声明了一个具有相同名称的函数,那么当使用print
时,则编译器会优先使用您的函数,因为当前模块中的函数比其他模块(包括Swift.
模块)中的函数更可取。
public func print(_ items: Any..., separator: String = " ", terminator: String = "\n") {
let output = items.map { "\($0)" }.joined(separator: separator)
Swift.print(output, terminator: terminator)
}
您可以在其中输入任何逻辑。
实际上,使用它从生产中删除日志记录非常常见,例如:
#if !DEBUG
func print(_ items: Any..., separator: String = " ", terminator: String = "\n") {}
func debugPrint(_ items: Any..., separator: String = " ", terminator: String = "\n") {}
#endif
有关更多详细信息,请参见Remove println() for release version iOS Swift。
从本质上讲,您可以通过在模块中重新声明整个Swift
模块来隐藏整个模块,例如作为enum
,因此禁止调用Swift.print
:
enum Swift {
public static func print(_ items: Any..., separator: String = " ", terminator: String = " ") {
// do something
}
}
但是,我通常不建议这样做,因为很难解决与Swift.
模块内部的标准库的任何命名冲突。
通常,我建议您实施自定义日志记录系统,并通过其他方式(例如,代码审查或棉绒规则(例如swiftlint)。
答案 1 :(得分:0)
方法Swizzling是Objective-C的运行时功能,由于Swift不是动态语言,因此它固有地在Swift中不可用。但是,您可以像此SO Post一样具有全局功能。以下是Swift 4.2的更新代码。
但不幸的是,如果函数名称为Swift.print
,它将调用原始的print
函数。所以我将函数名称更改为logs
public func logs(items: Any..., separator: String = " ", terminator: String = "\n") {
let output = items.map { "*\($0)"}.joined(separator: " ")
Swift.print(output, terminator: terminator)
}
另一个可能的选择是将其放入协议
public protocol CustomPrintable {
func print(_ items: Any...)
}
extension CustomPrintable {
func print(_ items: Any...) {
let output = items.map { "*\($0)"}.joined(separator: " ")
Swift.print("****" + output)
}
}
用法
class SampleClass : CustomPrintable {
func printValue() {
print ("Hello World")
}
}
但是这种方法不再是全局函数,在使用print
时,您必须选择正确的方法
输出
*****Hello World