2017-01-04 2 views
1

Я использую категорию на UIViewController для swizzle viewWillAppear: метод для нескольких ViewControllers.Метод 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 

Когда я загружаю исходный VC из раскадровки, метод swizzled никогда не вызывается. Он вызывается только в том случае, если метод viewWillAppear в VC закомментирован. Однако, когда я удаляю категорию и перемещаю код в отдельный 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 

Это нормально реализовать viewWillAppear в ВК, если он будет swizzled? Если нет, как мне это сделать, если мне нужно написать какой-то код в viewVillAppear VC?

+0

Попробуйте только 'method_exchangeImplementations', без добавления, как метод уже существует часть вашего расширения. – Cristik

+1

Кроме того, вы изучаете метод из базового класса, переопределяя его в своем пользовательском классе, поэтому вам нужно вызвать 'super', чтобы выполнить swizzled-метод. – Cristik

+0

@Cristik Я использую категорию, и я не подклассифицирую VC , – KrishnaKumar

ответ

2

Вам нужно позвонить super в вашем viewWillAppear: от ViewController, в противном случае метод из базового класса (UIViewController) не будет выполняться, и это тот, который вы swizzled.

Следующая версия viewWillAppear: должна дать вам ожидаемые результаты:

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