2017-02-20 6 views
0

두 가지 swizzling 방법에는 약간의 차이가 있습니다.이 두 메커니즘 사이를 swizzling 할 때의 차이점

@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을 사용하지 않고) : 근본적으로 다른 나 (class_addMethod를 사용하여) 우리가 UIView

첫 번째 방법에 viewDidLoad를 스위 즐링하는 가정

그들 사이에 뭔가 문제가있는 경우 그냥 설명을 원한다 :

+ (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

코드가 작동합니까? 선택기 swizzled_viewDidLoad에 대해 class_getInstanceMethod를 호출하지만 해당 함수는 인스턴스 메소드가 아닌 클래스 메소드입니다. –

답변

0

실제로 아주 좋은 질문입니다. 처음에 class_addMethod을 호출하지 않고 method_exchangeImplementations을 사용하면 실수로 수퍼 클래스 구현을 뒤집을 수 있습니다. 그 이유는 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] : 인식 할 수없는 선택기 removeFromSuperviewUIView에서 상속하지만 UIWebView에서 구현되지 0x101b24250

때문에 인스턴스에 보냈다.