2017-02-20 1 views
0

Es gibt eine leichte Abweichung zwischen diesen beiden Arten des Swizzlings. Ich will nur, Klärung, ob es etwas grundlegend anders oder falsch zwischen ihnen istWas ist der Unterschied beim Swizzling zwischen diesen beiden Mechanismen?

Angenommen, wir viewDidLoad auf UIView

Ersten Weg sind Swizzling (mit 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 

Zweitem Weg (ohne 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

Funktioniert Ihr Code? Sie rufen class_getInstanceMethod für selector swizzled_viewDidLoad auf, aber diese Funktion ist Klassenmethode, nicht Instanzmethode. –

Antwort

0

Sehr gute Frage, tatsächlich. Wenn Sie zuerst method_exchangeImplementations verwenden, ohne zuerst class_addMethod aufzurufen, können Sie Ihre Superklassenimplementierung versehentlich austauschen. Der Grund dafür ist, dass class_getInstanceMethod Oberklassen nach geerbter Implementierung durchsucht, wenn eine Methode nicht in der Klasse selbst implementiert ist. Und es ist offensichtlich nicht etwas, das Sie erreichen möchten.

Ein schnelles Beispiel. folgenden Code

@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 

Ergebnisse in

- [UICheckeredPatternView swizzled_removeFromSuperview]: Unbekannter Selektor an Instanz gesendet 0x101b24250

weil removeFromSuperview von UIView vererbt wird, aber nicht in UIWebView umgesetzt.

Verwandte Themen