Runtime 方法

2017-12-04  本文已影响3人  docallsama

各种方法

  1. class_addMethod 向类添加方法

添加方法需要的参数:类,方法名称,类中实现的方法,方法的属性

关于方法属性的参数:每个方法必须有至少两个参数- self 和 _cmd,则第一个字符为方法返回类型,第二、三个字符为"@"和":"。

方法添加成功之后再次添加就会返回false,这时候如果需要替换方法,只需要exchangeImplement即可。

更多方法类型参考链接
NSHipster中的介绍

- (void)addMethodForCar {
    Class carClass = objc_getClass("Car");
    BOOL isSuccess = class_addMethod(carClass, @selector(reverse), class_getMethodImplementation([self class], @selector(controllerReverse)), "v@:");
    
    if (isSuccess) {
        Car *fit = [[Car alloc] init];
        [fit performSelector:@selector(reverse) withObject:nil];
    }
}

//添加的方法实现
- (void)controllerReverse {
    NSLog(@"car reverse");
}
  1. class_copyMethodList 获取类声明方法
    category添加的方法也会在类的methodlist中出现,按照编译顺序category添加的方法会在类原本方法的前面。
//获取实体方法
unsigned int outcountMethod;
id PersonClass = objc_getClass("Car");
Method *methods = class_copyMethodList(PersonClass, &outcountMethod);
for (int i = 0; i < outcountMethod; i++) {
    Method method = methods[i];
    SEL methodSEL = method_getName(method);
    const char *selName = sel_getName(methodSEL);
    
    if (methodSEL) {
        NSLog(@"selector name -> %s",selName);
    }
}
free(methods);

// console output:
// selector name -> fakeRun
// selector name -> normalRun  iOSInterviewProblems`-[Person(MethodRun) normalRun] at Person+MethodRun.m:17
// selector name -> normalRun  iOSInterviewProblems`-[Person normalRun] at Person.m:40
  1. class_replaceMethod 替换已有的方法
Class PersonClass = objc_getClass("Person");
//声明替换的方法
IMP replaceIMP = class_getMethodImplementation([self class], @selector(playFootBall:));
//替换掉原有方法 
class_replaceMethod(PersonClass, @selector(innerMethod), replaceIMP, "v@:");

id person = [[PersonClass alloc] init];
[person performSelector:@selector(innerMethod) withObject:@"allen"];

// console output:
// allen is playing football
  1. method_exchangeImplementations 替换方法实现
//使用已有方法替换方法
Class PersonClass = objc_getClass("Person");
Method originalMethod = class_getInstanceMethod(PersonClass, @selector(originalMethodRun));
Method swizzledMethod = class_getInstanceMethod(PersonClass, @selector(swizzledMethodRun));
method_exchangeImplementations(originalMethod, swizzledMethod);
    
id person = [[PersonClass alloc] init];
[person performSelector:@selector(originalMethodRun) withObject:nil];

// console output:
// perform swizzled method run

参考代码 github链接

上一篇下一篇

猜你喜欢

热点阅读