2017-01-04 5 views
1

UIViewController에 범주를 사용하여 여러 ViewControllers에서 viewWillAppear : 메서드를 바꿀 수 있습니다.UIViewController 메서드 swizzling 작동하지 않습니다.

@implementation UIViewController (Tracking) 

+(void)load 
{ 
    static dispatch_once_t onceToken; 

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

     SEL originalSelector = @selector(viewWillAppear:); 
     SEL swizzledSelector = @selector(xx_viewWillAppear:); 

     Method originalMethod = class_getInstanceMethod(class, originalSelector); 
     Method swizzledMethod = class_getInstanceMethod(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); 
     } 

    }); 
} 

-(void)xx_viewWillAppear:(BOOL)animated 
{ 
    [self xx_viewWillAppear:animated]; 

    NSLog(@"VC loaded"); 
} 

@end 

Storyboard에서 초기 VC를로드 할 때 swizzled 메서드는 호출되지 않습니다. VC의 viewWillAppear 메소드가 주석 처리 된 경우에만 호출됩니다. 그러나 카테고리를 제거하고 코드를 개별 VC로 옮기면 두 메소드가 모두 호출됩니다.

#import "ViewController.h" 
#import "UIViewController+Tracking.h" 

@interface ViewController() 
@end 

@implementation ViewController 

- (void)viewDidLoad { 
    [super viewDidLoad]; 
    // Do any additional setup after loading the view, typically from a nib. 
} 

-(void)viewWillAppear:(BOOL)animated 
{ 
    NSLog(@"Inside Controller1"); 
} 

- (void)didReceiveMemoryWarning { 
    [super didReceiveMemoryWarning]; 
    // Dispose of any resources that can be recreated. 
} 

@end 

swizzled 경우 VC에 viewWillAppear 구현하는 것이 좋습니다 있습니까? 그렇지 않다면 VC의 viewWillAppear에 코드를 작성해야한다면 어떻게해야합니까?

+0

시도 만'method_exchangeImplementations',이 방법은 이미 확장의 일부를 존재, 추가하지 않고. – Cristik

+1

또한 메서드를 기본 클래스에서 swizelling, 사용자 정의 클래스에서 재정의하면 swizzled 메서드를 실행하기 위해'super'를 호출해야 함을 나타냅니다. – Cristik

+0

@Cristik @Cristik 범주를 사용하고 있는데 VC를 서브 클래 싱하지 않습니다. . – KrishnaKumar

답변

2

당신은 실행되지 않습니다 기본 클래스 (UIViewController)에서 달리 방법, ViewController에서 viewWillAppear:super를 호출 할 필요가, 그리고 당신이 스위 즐링 하나입니다.

viewWillAppear:의 다음 버전이 예상 결과를 당신에게 제공한다 :

-(void)viewWillAppear:(BOOL)animated 
{ 
    [super viewWillAppear:animated]; 
    NSLog(@"Inside Controller1"); 
}