小小文iOS DeveloperiOS开发笔记

iOS中的 Method_Swizzling

2017-07-07  本文已影响840人  dullgrass

黑魔法 Method_Swizzling

+(void)load +(void)initialize
执行时机 在main函数之前执行 在类的方法被第一次调用时执行
若自身未定义,是否沿用父类的方法?
类别中的定义 全都执行,但后于类中的方法 覆盖类中的方法,只执行一次
BOOL simple_Swizzle(Class aClass,SEL originalSel, SEL swizzleSel)
{
         Method originalMethod = class_getInstanceMethod(aClass, originalSel);
         Method swizzleMethod = class_getInstanceMethod(aClass,swizzleSel);
         method_exchangeImplementations(originalMethod, swizzleMethod);
         return YES;   
}
BOOL best_Swizzle(Class aClass, SEL originalSel, SEL swizzleSel)
{
         // 如果originalSel没有实现过,class_getInstanceMethod无法找到该方法,所以originalMethod为nil
         Method originalMethod = class_getInstanceMethod(aClass, originalSel);
         Method swizzleMethod = class_getInstanceMethod(aClass, swizzleSel);
         BOOL didAddMethod = class_addMethod(aClass, originalSel, method_getImplementation(swizzleMethod), method_getTypeEncoding(swizzleMethod));
         if (didAddMethod) {
             //  当originalMethod为nil时,这里的class_replaceMethod将不做替换,所以swizzleSel方法里的实现还是自己原来的实现
             class_replaceMethod(aClass, swizzleSel, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
         } else {
             method_exchangeImplementations(originalMethod, swizzleMethod);
         }
         return YES;
}
if (!originalMethod)  {
          class_addMethod(aClass, originalSel, method_getImplementation(swizzleMethod), method_getTypeEncoding(swizzleMethod));
          method_setImplementation(swizzleMethod, imp_implementationWithBlock(^(id self, SEL _cmd){ }));        
}

Method_Swizzling的具体用途AOP(面向切面编程)

  1. 页面统计(AOP)、NSMutableArray的insert等插入nil,hook: 給全局图片名称添加前缀,分类中为已有的属性或者方法添加钩子(增加一段代码)
  2. 用于记录或者存储,比方说记录ViewController进入次数、Btn的点击事件、ViewController的停留时间等等。 可以通过Runtime获取到具体ViewController、Btn信息,然后传给服务器
  3. 添加需要而系统没提供的方法,比方说修改Statusbar颜色。用于轻量化、模块化处理
  4. 用Method Swizzle 动态给指定的方法添加代码,以解决Cross-cutting concern的编程方式叫做Aspect Oriented Programming,将逻辑处理和事件记录的代码解耦
  5. AOP可以把琐碎的事务从主逻辑中分离出来,作为单独的模块,它是对面向对象编程模式的一种补充
  6. 比较好的AOP库,封装了runtime,Method Swizzling这些黑科技,该库只有两个API
      + (id<AspectToken>)aspect_hookSelector:(SEL)selector
                                  withOptions:(AspectOptions)options
                                   usingBlock:(id)block
                                        error:(NSError **)error;
      - (id<AspectToken>)aspect_hookSelector:(SEL)selector
                                  withOptions:(AspectOptions)options
                                   usingBlock:(id)block
                                        error:(NSError **)error;

Objective-C类的继承、方法的重写和重载

  1. 继承:Objective-c中类的继承与C++类似,不同的是Objective-c不支持多重继承,一个类只能有一个父类,单继承使Objective-c的继承关系很简单,易于管理程序
  2. 重写:在Objective-c中,子类可继承父类中的方法,而不需要重新编写相同的方法,直接可以使用父类的方法。
    但有时我们不想使用使用父类方法,而是想作一定的修改,怎么办呢?只要将子类中书写一个与父类具有相同的方法名、返回类型和参数,就可以将将父类的方法覆盖重写
OverRide *overRide = (OverRide*)[[NSClassFromString(@"SubOverRide") alloc] init];
[overRide superMethod];
  1. 重载:在Objective-c中,方法是不能重载的。也就是说我们不能在类中定义这样的两个方法:它们的名子相同,参数个数相同,参数类型不同,不同的返回值类型。否则Xcode会报错。

引用

上一篇 下一篇

猜你喜欢

热点阅读