我试图更改设备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
出了什么问题?
答案 0 :(得分:3)
你的第一种方法是正确的混合实例方法, 但不适用于班级方法。 如果我理解正确的话会发生什么
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);
转换为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)
}
}
然后如预期般的混合工作。 (关键是这一点
class_addMethod()
在类对象上调用,而不在self
上调用。)
但实际上我没有看到你的第二种方法有任何优势。
didAddMethod
将始终返回false
,因为frLocale
已被定义为NSLocale
的类方法。