runtime运行时应用场景-method swizzling

实际开发中可能面临这样的需求:

  • 需要把所有的UILabel的字体放大2号
  • 需要给所有ViewController添加友盟统计

简单粗暴地方法就是UILabel和ViewController挨个改,但是作为一个程序员,这样改就太丢人了。就算不考虑自己的面子,也总得为公司的发展大计着想吧。

如果是项目开始,可以考虑建个BaseViewController,或者用Category也能实现。可是如果是项目已经有了一定规模之后,再提出以上需求,就需要用到更深层次的技术(runtime)了。

先是UILabel字体大小的问题,新建一个UILabel的category

#import   
@interface UILabel (WFFontLabel)  
@end 

具体实现

    #import "UILabel+WFFontLabel.h"  
    #import   
      
    @implementation UILabel (WFFontLabel)  
      
    + (void)load {  
        static dispatch_once_t onceToken;  
        dispatch_once(&onceToken, ^{  
            Class class = [self class];  
      
            // 获取两个方法的IMP(指针)  
            Method originalMethod2 = class_getInstanceMethod(class, @selector(setFont:));  
            Method swizzledMethod2 = class_getInstanceMethod(class, @selector(WFSetFont:));  
      
            // 交换IMP  
            method_exchangeImplementations(originalMethod2, swizzledMethod2);  
      
        });  
    }  
      
    - (void)WFSetFont:(UIFont *)font {  
        UIFont * newFont = [UIFont systemFontOfSize:font.pointSize+10];  
        [self WFSetFont:newFont];  
    }  
      
    @end  

当然,如果想更严谨一些,可以写成下面这样(个人认为没有必要)

static dispatch_once_t onceToken;  
   dispatch_once(&onceToken, ^{  
       Class class = [self class];  
  
       Method originalMethod2 = class_getInstanceMethod(class, @selector(setFont:));  
       Method swizzledMethod2 = class_getInstanceMethod(class, @selector(WFSetFont:));  
  
       BOOL didAddMethod2 = class_addMethod(class, @selector(setFont:), method_getImplementation(swizzledMethod2), method_getTypeEncoding(swizzledMethod2));  
  
       if (didAddMethod2) {  
           class_replaceMethod(class,  
                               @selector(WFSetFont:),  
                               method_getImplementation(originalMethod2),  
                               method_getTypeEncoding(originalMethod2));  
       }else {  
           method_exchangeImplementations(originalMethod2, swizzledMethod2);  
       }  
  
   });

另外一个给所有ViewController添加友盟统计,类似的,新建一个viewcontroller的category

    #import   
    @interface UIViewController (WFAnalysis)  
    @end  

具体实现

    #import "UIViewController+WFAnalysis.h"  
    #import   
    
    @implementation UIViewController (WFAnalysis)  
      
    + (void)load {  
        [super load];  
        Method orgMethod = class_getInstanceMethod([self class], @selector(viewWillAppear:));  
        Method swizzledMethod = class_getInstanceMethod([self class], @selector(customViewWillAppear:));  
      
        method_exchangeImplementations(orgMethod, swizzledMethod);  
    }  
      
    - (void)customViewWillAppear:(BOOL)animated {  
        [self customViewWillAppear:animated];  
        NSLog(@"可以在这里添加统计代码");  
    }  
      
    @end  

原文地址:http://blog.csdn.net/zwf_apple/article/details/53127706

你可能感兴趣的:(runtime运行时应用场景-method swizzling)