2017-02-20 20 views
0

Существует небольшое изменение между этими двумя способами swizzling. Я просто хочу разъяснить, если есть что-то принципиально отличается или нет между нимиВ чем разница, когда вы двигаетесь между этими двумя механизмами

Предполагая, что мы swizzling viewDidLoad на UIView

Первый способ (с использованием 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 
+0

Работает ли ваш код? вы вызываете class_getInstanceMethod для selector swizzled_viewDidLoad, но эта функция - метод класса, а не метод экземпляра. –

ответ

0

Очень хороший вопрос, на самом деле. Если вы используете 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.

 Смежные вопросы

  • Нет связанных вопросов^_^