NSLocale 使用方法 swizzling 更改 currentLocale 输出以进行测试
NSLocale using method swizzling to change the currentLocale output for testing purposes
我正在尝试更改设备 currentLocale 输出以执行一些有趣的单元测试,这是我正在使用的代码,但返回的 currentLocale 似乎没有被覆盖。有什么提示吗?
extension NSLocale {
class func frLocale()->NSLocale{
return NSLocale(localeIdentifier: "fr_FR")
}
class func forceCurrentLocale(){
let originalSelector = #selector(NSLocale.currentLocale)
let swizzledSelector = #selector(self.frLocale)
let originalMethod = class_getClassMethod(self, originalSelector)
let swizzledMethod = class_getClassMethod(self, swizzledSelector)
let didAddMethod = class_addMethod(self, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod))
if didAddMethod {
class_replaceMethod(self, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod))
} else {
method_exchangeImplementations(originalMethod, swizzledMethod)
}
}
}
// 编辑
上面的代码不起作用。但是如果我这样写它就可以了:
class func forceCurrentLocale(){
let originalSelector = #selector(NSLocale.currentLocale)
let swizzledSelector = #selector(NSLocale.frLocale)
let originalMethod = class_getClassMethod(self, originalSelector)
let swizzledMethod = class_getClassMethod(self, swizzledSelector)
method_exchangeImplementations(originalMethod, swizzledMethod)
}
在那种情况下 class_addMethod
有什么问题?
你的第一个方法是正确的,可以调配一个实例方法,
但不适用于 class 方法。
发生了什么——如果我理解正确的话——是
let didAddMethod = class_addMethod(self, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod))
将 实例方法 添加到 class 和 return 的 true
。然后
class_replaceMethod(self, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod))
替换失败的实例方法。
如果您查看来自 NSHipster 的 Method Swizzling 文章,您会发现以下评论:
// When swizzling a class method, use the following:
// Class class = object_getClass((id)self);
// ...
// Method originalMethod = class_getClassMethod(class, originalSelector);
// Method swizzledMethod = class_getClassMethod(class, swizzledSelector);
翻译成 Swift 即
class func forceCurrentLocale(){
let originalSelector = #selector(NSLocale.currentLocale)
let swizzledSelector = #selector(self.frLocale)
let classObject : AnyClass = object_getClass(self)
let originalMethod = class_getClassMethod(classObject, originalSelector)
let swizzledMethod = class_getClassMethod(classObject, swizzledSelector)
let didAddMethod = class_addMethod(classObject, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod))
if didAddMethod {
class_replaceMethod(self, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod))
} else {
method_exchangeImplementations(originalMethod, swizzledMethod)
}
}
然后 swizzling 按预期工作。 (关键点在于
class_addMethod()
在 class 对象上调用,而不是在 self
上调用。)
但实际上我看不出比你的第二种方法有任何优势。
didAddMethod
将永远 return false
因为 frLocale
已经定义为 NSLocale
.
的 class 方法
我正在尝试更改设备 currentLocale 输出以执行一些有趣的单元测试,这是我正在使用的代码,但返回的 currentLocale 似乎没有被覆盖。有什么提示吗?
extension NSLocale {
class func frLocale()->NSLocale{
return NSLocale(localeIdentifier: "fr_FR")
}
class func forceCurrentLocale(){
let originalSelector = #selector(NSLocale.currentLocale)
let swizzledSelector = #selector(self.frLocale)
let originalMethod = class_getClassMethod(self, originalSelector)
let swizzledMethod = class_getClassMethod(self, swizzledSelector)
let didAddMethod = class_addMethod(self, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod))
if didAddMethod {
class_replaceMethod(self, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod))
} else {
method_exchangeImplementations(originalMethod, swizzledMethod)
}
}
}
// 编辑
上面的代码不起作用。但是如果我这样写它就可以了:
class func forceCurrentLocale(){
let originalSelector = #selector(NSLocale.currentLocale)
let swizzledSelector = #selector(NSLocale.frLocale)
let originalMethod = class_getClassMethod(self, originalSelector)
let swizzledMethod = class_getClassMethod(self, swizzledSelector)
method_exchangeImplementations(originalMethod, swizzledMethod)
}
在那种情况下 class_addMethod
有什么问题?
你的第一个方法是正确的,可以调配一个实例方法, 但不适用于 class 方法。 发生了什么——如果我理解正确的话——是
let didAddMethod = class_addMethod(self, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod))
将 实例方法 添加到 class 和 return 的 true
。然后
class_replaceMethod(self, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod))
替换失败的实例方法。
如果您查看来自 NSHipster 的 Method Swizzling 文章,您会发现以下评论:
// When swizzling a class method, use the following:
// Class class = object_getClass((id)self);
// ...
// Method originalMethod = class_getClassMethod(class, originalSelector);
// Method swizzledMethod = class_getClassMethod(class, swizzledSelector);
翻译成 Swift 即
class func forceCurrentLocale(){
let originalSelector = #selector(NSLocale.currentLocale)
let swizzledSelector = #selector(self.frLocale)
let classObject : AnyClass = object_getClass(self)
let originalMethod = class_getClassMethod(classObject, originalSelector)
let swizzledMethod = class_getClassMethod(classObject, swizzledSelector)
let didAddMethod = class_addMethod(classObject, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod))
if didAddMethod {
class_replaceMethod(self, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod))
} else {
method_exchangeImplementations(originalMethod, swizzledMethod)
}
}
然后 swizzling 按预期工作。 (关键点在于
class_addMethod()
在 class 对象上调用,而不是在 self
上调用。)
但实际上我看不出比你的第二种方法有任何优势。
didAddMethod
将永远 return false
因为 frLocale
已经定义为 NSLocale
.