运行时

作者: 观星 | 来源:发表于2018-07-13 14:04 被阅读8次

    运行时

    - (void)noReturnNoParams {
        NSLog(@"noReturnNoParams");
    }
    
    - (NSString *)hasReturnHasParams:(NSString *)params {
        NSLog(@"hasReturnHasParams:%@",params);
        
        return params;
    }
    
    

    调用

    // 一般调用
    [self noReturnNoParams];
    [self hasReturnHasParams:@"params"];
    
    // 通过objc_msgSend调用
    ((void(*)(id,SEL))objc_msgSend)(self,@selector(noReturnNoParams));
    ((NSString *(*)(id,SEL,NSString *))objc_msgSend)(self,@selector(hasReturnHasParams:),@"this is param");
    
    // 通过函数地址调用
    void (*setter)(id,SEL);
    setter = (void(*)(id, SEL, BOOL))[self methodForSelector:@selector(noReturnNoParams)];
    setter(self, @selector(noReturnNoParams));
    
    

    消息转发

    通过 obj_msgSend 调用,在找不到imp的时候,就会进入消息转发流程

    1. 调用 + (BOOL)resolveInstanceMethod:(SEL)sel; 如果重写这个方法,动态添加未实现的方法,转发流程结束。

      + (BOOL)resolveInstanceMethod:(SEL)sel {
          NSLog(@"resolveInstanceMethod");
          
          if (sel == @selector(nofunction)) {
              
              IMP imp = imp_implementationWithBlock(^{
                  NSLog(@"既然没有实现,那就动态添加方法");
              });
      
              class_addMethod([ObjcMsgSendVC class], sel, imp, "v@:");
              
                // return YES/NO不知道有什么作用,看起来没什么影响
              return NO;
          }
          
          return [super resolveInstanceMethod:sel];
      }
      
      
    2. 触发 - (id)forwardingTargetForSelector:(SEL)aSelector ;可以指定一个对象来相应这个方法,如果返回nil,则进入下一步

      - (id)forwardingTargetForSelector:(SEL)aSelector {
          NSLog(@"forwardingTargetForSelector:");
          
          if (aSelector == @selector(nofunction)) {
              // Obviously if you return self from this method, the code would just fall into an infinite loop.
              // 但是系统做了优化,返回self也没事,但是不建议这么做
              return self.delegate;
          } else {
              return [super forwardingTargetForSelector:aSelector];
          }
      }
      
    3. 正常转发,可以传递给多个对象

      - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector {
          NSLog(@"methodSignatureForSelector:");
          
          if (aSelector == @selector(nofunction)) {
              // return nil;就不会调用下一步forwardInvocation:
              return [self methodSignatureForSelector:@selector(showWithAnimated:)];
          } else {
              return [super methodSignatureForSelector:aSelector];
          }
      }
      
      - (void)forwardInvocation:(NSInvocation *)anInvocation {
          NSLog(@"forwardInvocation:");
          
          if (anInvocation.selector == @selector(nofunction)) {
              NSLog(@"anInvocation.selector == @selector(nofunction)");
              
              [self showWithAnimated:YES];
              
          } else {
              [super forwardInvocation:anInvocation];
          }
      }
      

    添加方法

    SEL selector = @selector(test);
        
    IMP imp =imp_implementationWithBlock(^{
        NSLog(@"这是方法实现");
    });
        
    Method method = class_getInstanceMethod([AddMethodVC class], selector);
        
    class_addMethod([AddMethodVC class], selector, imp, method_getTypeEncoding(method));
    

    方法交换

    - (void)origin {
        NSLog(@"originMethod");
    }
    
    - (void)swizzle {
        NSLog(@"这是Swizzle方法实现");
    }
    
    - (void)swizzleMethod {
        SEL originSel = @selector(origin);
        SEL swizzleSel = @selector(swizzle);
        
        Method originMethod = class_getInstanceMethod([SwizzleMethodVC class], originSel);
        Method swizzleMethod = class_getInstanceMethod([SwizzleMethodVC class], swizzleSel);
        
        // 确定方法存在就可以直接交换,否则可以考虑,如果方法不存在,可以先添加
        BOOL didAddMethod = class_addMethod([SwizzleMethodVC class], originSel, method_getImplementation(swizzleMethod), method_getTypeEncoding(swizzleMethod));
        
        if (didAddMethod) {
            class_replaceMethod([SwizzleMethodVC class], swizzleSel, method_getImplementation(originMethod), method_getTypeEncoding(originMethod));
        } else {
            method_exchangeImplementations(originMethod, swizzleMethod);
        }
    }
    
    

    方法替换

    - (void)replaceMethod {
        
    //    Method method = class_getInstanceMethod([ReplaceMethodVC class], @selector(swizzle));
    //
    //    class_replaceMethod([ReplaceMethodVC class], @selector(origin), method_getImplementation(method), method_getTypeEncoding(method));
        
        Method method = class_getInstanceMethod([ReplaceMethodVC class], @selector(origin));
        
        IMP imp = imp_implementationWithBlock(^{
            NSLog(@"这是新的方法实现");
        });
        
        class_replaceMethod([ReplaceMethodVC class], @selector(origin), imp, method_getTypeEncoding(method));
    }
    
    - (void)origin {
        NSLog(@"originMethod");
    }
    
    - (void)swizzle {
        NSLog(@"这是Swizzle方法实现");
    }
    
    

    传送门

    项目地址

    相关文章

      网友评论

          本文标题:运行时

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