블랙 매직 (방법 - 스위 즐링)는 타사 라이브러리에 의해 발생하는 문제를 해결하기 위해

 

2019 년 2 월 21 일 업데이트

수요

최근의 프로젝트는 수요가있는 모든 네트워크 요청 (즉, 상태 표시 줄에 작은 원을 회전) NetworkActvityIndicator을 표시되지 않습니다.

해결 방법 1 :

NetworkIndicator 글로벌 검색 키워드는, 모든 코드는 예를 들어, NetworkIndicator 제거를 포함 [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];.

테스트는 새로운 문제를 발견

인터페이스는 여전히 재생 비디오 디스플레이입니다 제외하고 모든 인터페이스는 더 이상 NetworkActvityIndicator 표시되지 않습니다.

추측 : 타사 라이브러리로 인한 문제를

아무리 정상적인 상황에서 타사 라이브러리는 상태 표시 줄 setNetworkActivityIndicatorVisible을 통해 작은 원이 될 것입니다 무슨.

검증 과정 (1)

상속 UIApplication을 통해 setNetworkActivityIndicatorVisible 방법을 다시 작성합니다. (UIApplication을 상속하는 방법, 여기 참조) 및 메소드 본문에 중단 점 히트를 넣어.

테스트 정상 호출은 [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];중단 점을 트리거합니다. 그러나 비디오 인터페이스, 중단 점, 일반 디스플레이 작은 원을 유발하지 않았다 유일한 경우.

검증 과정 2

networkActivityIndicatorVisible 재산의 KVO 청취 UIApplication으로, 결과는 같은 상황 및 검증 1이었다.
일반 전화는 [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];트리거 모니터하지 않고, 그 비디오 인터페이스를 제외하고, 모니터를 유발하고, 일반 디스플레이 작은 원됩니다.

따라서, 일반적인 호출 영상 표시 작은 원의 화면과 확실히이 setNetworkActivityIndicatorVisible방법을 표시.

업데이트 추측 : 문제는 타사 라이브러리에 의한, 대신 기존의 방법으로 호출

검증 과정 3

상태 표시에있는 작은 원 인터페이스의 뷰 구조 분석을 보여 UIActivityIndicatorView 타입 뷰 (두 홀수의 존재)이 존재한다.

정상적인 상황 즉,로 [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES];작은 원을 표시, 뷰 계층은 어떻게입니까? 분석에 의한 검증은 동일하다.

레벨은 UIStatusBarView -> UIStatusBarForegroundView -> UIStatusBarActivityItemView -> UIActivityIndicatorView

솔루션의 생각 :

UIActivityIndicatorView 루틴 호출하는 애니메이션을 시작하면서 작은 원하기 때문에 뷰의 UIActivityIndicatorView 유형이 있습니다 startAnimation방법을.
그런데 왜 그 무시하는 마술 (방법 스위 즐링)를 사용하지 startAnimation, 방법을
만약 그렇다면, 직접 그것을 밖으로 수퍼 "UIStatusBarActivityItemView"타입 여부를 결정합니다. 그렇지 않으면, 원래 startAnimation 방법.

토크는 저렴합니다. 나에게 코드를 표시합니다.

여기에 코드하는 .m 파일입니다

@implementation UIActivityIndicatorView (HideNetworkActivityIndicator)

+ (void)load {

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

        SEL originalSelector = @selector(startAnimating);
        SEL swizzledSelector = @selector(xxx_startAnimating);

        Method originalMethod = class_getInstanceMethod(class, originalSelector);
        Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);

        // When swizzling a class method, use the following:
        // 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_startAnimating{

    if (self.superview != nil && [NSStringFromClass([self.superview class]) isEqualToString: @"UIStatusBarActivityItemView"]) {
        NSLog(@"黑魔法禁止状态栏的loading显示: %@", self);
    } else {
        [self xxx_startAnimating];
    }

}


@end

성공! ! !

(생체 xxx_startAnimation 브레이크 포인트, 비디오 플레이어 인터페이스 프로그램을 시작, 중단 점을 트리거, 호출 스택은 정말 타사 라이브러리로 인한 문제가, 볼 수 있습니다.)

참조 : https://nshipster.cn/method-swizzling/

추천

출처www.cnblogs.com/ZJT7098/p/hei-mo-fa-methodswizzling-jie-jue-di-san-fang-ku-y.html