NSLocale使用方法swizzling改变currentLocale输出为测试目的
问题描述:
我想改变设备currentLocale输出执行一些有趣的单元测试,这是我使用的代码,但它似乎返回currentLocale doesn'不会被覆盖。任何提示?NSLocale使用方法swizzling改变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
有什么问题?
答
你的第一种方法是修改实例方法 ,但不适用于类方法。 会发生什么 - 如果我理解正确的话 - 是
let didAddMethod = class_addMethod(self, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod))
增加了一个实例方法到类,并返回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);
翻译斯威夫特,这将是
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)
}
}
,然后混写按预期工作。 (关键是 class_addMethod()
在类对象上被调用,而不是在self
上。)
但实际上我没有看到你的第二种方法有什么优势。 didAddMethod
将始终返回false
,因为frLocale
已被定义为NSLocale
的类方法。