[英]What is the difference when swizzling between these 2 mechanisms
這兩種方式之間存在細微的差異。 我只是想澄清一下它們之間是否存在根本上的不同或錯誤
假設我們在UIView
上浪費了viewDidLoad
第一種方式(使用class_addMethod
):
@implementation UIView (SwizzleFirstWay)
+ (void)load {
SEL originalSelector = @selector(viewDidLoad);
SEL swizzledSelector = @selector(swizzled_viewDidLoad);
Method originalMethod = class_getInstanceMethod(self, originalSelector);
Method swizzledMethod = class_getInstanceMethod(self, swizzledSelector);
class_addMethod(self,
originalSelector,
class_getMethodImplementation(self, originalSelector),
method_getTypeEncoding(originalMethod));
// Adding the method
class_addMethod(self,
swizzledSelector,
class_getMethodImplementation(self, swizzledSelector),
method_getTypeEncoding(swizzledMethod));
method_exchangeImplementations(originalMethod, swizzledMethod);
}
+ (void)swizzled_viewDidLoad {
// ... the swizzled implementation
// ...
// ...
[self swizzled_viewDidLoad]; // calling back to the original implementation
}
@end
第二種方式(不使用class_addMethod
):
+ (void)load {
SEL originalSelector = @selector(viewDidLoad);
SEL swizzledSelector = @selector(swizzled_viewDidLoad);
Method originalMethod = class_getInstanceMethod(self, originalSelector);
Method swizzledMethod = class_getInstanceMethod(self, swizzledSelector);
// NOT USING class_addMethod
method_exchangeImplementations(originalMethod, swizzledMethod);
}
+ (void)swizzled_viewDidLoad {
// ... the swizzled implementation
// ...
// ...
[self swizzled_viewDidLoad]; // calling back to the original implementation
}
@end
實際上,這是一個很好的問題。 如果您使用method_exchangeImplementations
沒有調用class_addMethod
第一,你可能會意外地調配你的超類實現。 原因是class_getInstanceMethod
在類本身未實現方法的情況下,在超類中搜索繼承的實現。 顯然,這不是您想要實現的目標。
一個簡單的例子。 使用以下代碼
@interface UIWebView (SwizzlingTest)
- (void)swizzled_removeFromSuperview {
[self swizzled_removeFromSuperview];
}
+ (void)load {
SEL originalSelector = @selector(removeFromSuperview);
SEL swizzledSelector = @selector(swizzled_removeFromSuperview);
Method originalMethod = class_getInstanceMethod(self, originalSelector);
Method swizzledMethod = class_getInstanceMethod(self, swizzledSelector);
method_exchangeImplementations(originalMethod, swizzledMethod);
}
@end
結果是
-[UICheckeredPatternView swizzled_removeFromSuperview]:無法識別的選擇器已發送到實例0x101b24250
因為removeFromSuperview
繼承自UIView
,但未在UIWebView
實現。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.