iOS Swizzle Method

作者: 鄙人哈哈哈哈5871 | 来源:发表于2016-09-10 15:48 被阅读910次

    1.实例方法交换

    + (void)load
    {
      static dispatch_once_t onceToken;
      dispatch_once(&onceToken, ^{
    
      Method origleMe = class_getInstanceMethod([self class], @selector(viewWillAppear:)); // 如果子类没有实现  这个获取到的是superClass的方法
      Method newMe = class_getInstanceMethod([self class], @selector(my_viewWillAppear:));
    
    // 这个方法  往类里面添加 方法
    //1.如果类没有实现这个方法,class_addMethod给类添加一个方法,方法的选择器还是它本身,方法的实现和参数类型都是要替换的新的方法,这种情况返回的bool是YES,在调用class_replaceMethod替换新增的方法的实现为继承的superclass的方法实现,
    
    // 疑问1 class_addMethod 如果添加成功,添加的方法的实现其实是新增的方法的实现,class_replaceMethod 替换的时候获取方法IMP时候应该用最开始获取的method,如果不这样有可能用,再次获取Method那么class_replaceMethod替换的还是新增的方法,相当于系统的和新的方法的实现都是新增的实现 验证 正确 ,如果这样写 会循环调用
     //2.如果类里面以及有这个方法,class_addMethod添加失败,直接交换两个方法的实现即可
       BOOL isSuccess = class_addMethod([self class], @selector(viewWillAppear:), method_getImplementation(newMe), method_getTypeEncoding(newMe));
    
    // 测试 疑问1
    //    Method aOrigleMe = class_getInstanceMethod([self class], @selector(viewWillAppear:));
       if (isSuccess) {
            class_replaceMethod([self class], method_getName(newMe), method_getImplementation(origleMe), method_getTypeEncoding(origleMe));
    // 测试 疑问1
    //      class_replaceMethod([self class], method_getName(newMe), method_getImplementation(aOrigleMe), method_getTypeEncoding(aOrigleMe));
        } else {
            method_exchangeImplementations(origleMe, newMe);
        }
      });
    }
    - (void)my_viewWillAppear:(BOOL)animated
    {
         [self my_viewWillAppear:animated];
    //  [self viewWillAppear:animated];
         NSLog(@"%s",__func__);
    }
    

    2.类方法交换

    + (void)load
    {
      static dispatch_once_t onceToken;
      dispatch_once(&onceToken, ^{
      // 这个应为要获取类方法,所以需要获取到元类对象
      // 因为实例方法存放在类对象里面,类方法存放在元类对象里面
      Class aClass = object_getClass(self);
    
    
      SEL orgiSel = @selector(testOrgiClassMethod);
      SEL newSel = @selector(testNewClassMethod);
    
      Method oriClassMe = class_getClassMethod(aClass, orgiSel);
      Method newClassMe = class_getClassMethod(aClass, newSel);    
        BOOL isSuccess = class_addMethod(aClass, orgiSel, method_getImplementation(newClassMe), method_getTypeEncoding(newClassMe));
        if (isSuccess) {
          class_replaceMethod(aClass, newSel, method_getImplementation(oriClassMe), method_getTypeEncoding(oriClassMe));
        } else {
        method_exchangeImplementations(oriClassMe, newClassMe);
        }
      });
    }
    
    + (void)testOrgiClassMethod
    {
      NSLog(@"%s",__func__);
    }
    
    + (void)testNewClassMethod
    {
      NSLog(@"%s",__func__);
    }
    

    3.class一点总结

    // +(Class)class{return self}  -(Class)class{return object_getClass(self)}
    /*  
     实例对象
     1. -(Class)class; 获取到类对象
     2. object_getClass(self); 获取到类对象
     3. object_getClass([self class]); 获取元类
     类对象
     1.+(Class)class; 获取到还是本身
     2.object_getClass(self); 获取到元类对象
     3.object_getClass([self class]); 获取元类对象
    
    
     // 为神魔  在一个类里面 [self class] == [super class];
    
     应为oc的方法调用都会是转成消息
     [self class] 会调用 objc_msgSend(self,@selecter(class)); 
     [super class] 会调用  objc_msgSendSuper(struct objc_super *super, SEL)
    
    // 这个结构体里面的 receiver 就是self 调用super时他会从父类开始查找class的方法,但是消息的接受者还是 self ,所以打印的它俩相同
    
       struct objc_super {
          Specifies an instance of a class.
          __unsafe_unretained id receiver;
    
          Specifies the particular superclass of the instance to message.
          #if !defined(__cplusplus)  &&  !__OBJC2__
          For compatibility with old objc-runtime.h header
          __unsafe_unretained Class class;
          #else
          __unsafe_unretained Class super_class;
          #endif
          super_class is the first class to search
        };
    
    
     // 发消息,系统会自动从下面几个中间挑选合适的调用
    
       objc_msgSend  objc_msgSend_stret  objc_msgSendSuper  objc_msgSendSuper_stret
    
       * @note When it encounters a method call, the compiler generates a call to one of the
       *  functions \c objc_msgSend, \c objc_msgSend_stret, \c objc_msgSendSuper, or \c objc_msgSendSuper_stret.
       *  Messages sent to an object’s superclass (using the \c super keyword) are sent using \c objc_msgSendSuper;
       *  other messages are sent using \c objc_msgSend. Methods that have data structures as return values
       *  are sent using \c objc_msgSendSuper_stret and \c objc_msgSend_stret.
    */
    

    项目地址:https://github.com/hkkh/iOS-Swizzle-Method.git

    相关文章

      网友评论

        本文标题:iOS Swizzle Method

        本文链接:https://www.haomeiwen.com/subject/ctiyettx.html