iOS runtime Method Swizzling

3265 단어
흑마법 Method Swizzling
사실은 두 가지 방법을 교환하는 실현이다.
주로 사용되는 방법에 대한 정의를 살펴보겠습니다.
void method_exchangeImplementations(Method m1, Method m2)

예를 들어 프로그램에서 모든view controller가 사용자에게 보여준 횟수를 추적하고 싶습니다. 물론 모든view controller의view Did Appear에 추적 코드를 추가할 수 있습니다.그러나 이것은 너무 번거로워서 모든view controller에 중복된 코드를 써야 합니다.하위 클래스를 만드는 것은 일종의 실현 방식일 수 있지만, UIViewController, UItableViewController, UINavigationController 및 기타 UIKit에서viewcontroller의 하위 클래스를 동시에 만들어야 한다. 이 역시 많은 중복된 코드를 만들 수 있다.
이 경우 다음 코드와 같이 Method Swizzling을 사용할 수 있습니다.
#import 

@implementation UIViewController (Tracking)

+ (void)load {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Class class = [self class];

        SEL originalSelector = @selector(viewWillAppear:);
        SEL swizzledSelector = @selector(xxx_viewWillAppear:);
        
        //    
        Method originalMethod = class_getInstanceMethod(class, originalSelector);
        Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);

        //    
        // Class class = object_getClass((id)self);
        // ...
        // Method originalMethod = class_getClassMethod(class, originalSelector);
        // Method swizzledMethod = class_getClassMethod(class, swizzledSelector);

        //           ,                 
        BOOL didAddMethod =
            class_addMethod(class,
                originalSelector,
                method_getImplementation(swizzledMethod),
                method_getTypeEncoding(swizzledMethod));

        if (didAddMethod) {
             //    :                 
            class_replaceMethod(class,
                swizzledSelector,
                method_getImplementation(originalMethod),
                method_getTypeEncoding(originalMethod));
        } else {
            //    :          ,              
            method_exchangeImplementations(originalMethod, swizzledMethod);
        }
    });
}

#pragma mark - Method Swizzling

- (void)xxx_viewWillAppear:(BOOL)animated {
    [self xxx_viewWillAppear:animated];
    NSLog(@"viewWillAppear: %@", self);
}

@end

여기서 method swizzling을 통해 UIView Controller의 @selector(view Will Appear:)에 대응하는 함수 포인터를 수정하여 사용자 정의 xx 를 가리킵니다view Will Appear의 실현.이렇게 하면 UIViewController와 하위 클래스의 대상이viewWillAppear를 호출할 때 로그 정보를 출력합니다.
주의 사항
Swizzling은 항상 +load에서 수행해야 합니다.
Objective-C에서는 런타임에 각 클래스에 대해 두 가지 메서드가 자동으로 호출됩니다. +load는 클래스가 처음 불러올 때 호출되며, +initialize는 클래스를 처음 호출하기 전에 호출됩니다.이 두 가지 방법은 선택할 수 있으며, 그것들을 실현할 때만 호출될 수 있다.method swizzling은 클래스의 전체 상태에 영향을 미치기 때문에 병행 처리 과정에서 경쟁이 발생하는 것을 최대한 피해야 한다.load는 클래스의 초기화 과정에서 불러오는 것을 보장하고 응용 단계를 바꾸는 행위의 일치성을 보장합니다.그에 비해 +initialize는 실행할 때 이러한 보증을 제공하지 않습니다. 사실상, 응용 프로그램에서 이 클래스에 메시지를 보내지 않으면 영원히 호출되지 않을 수도 있습니다.
Swizzling은 항상 디스패치에서...once에서 실행
위와 마찬가지로 swizzling은 전체 상태를 바꿀 수 있기 때문에 우리는 운행할 때 예방 조치를 취해야 한다.원자성은 코드가 몇 개의 라인이 있든지 간에 한 번만 실행될 수 있도록 하는 조치이다.GCD의 dispatchonce는 이러한 행위를 확보할 수 있으며, 우리는method swizzling의 가장 좋은 실천으로 삼아야 한다.
소결
이 영화는 주로 흑마법 Method Swizzling의 사용 방법과 주의사항을 소개했다. Method Swizzling에 대한 유연한 운용을 통해 업무량이 끊임없이 증가하는 동시에 코드의 낮은 결합도를 유지하고 유지 보수의 작업량과 난이도를 낮추는 데 도움이 될 것이다.
참고 자료
https://nshipster.com/method-swizzling/

좋은 웹페이지 즐겨찾기