美文网首页
总结几个iOS runtime经常使用的方法

总结几个iOS runtime经常使用的方法

作者: Jason__Zhou | 来源:发表于2019-11-22 16:05 被阅读0次

上来直接就写代码

一.获取属性列表并修改其中属性的值:

    unsigned int count = 0;
    // 获取person里的所有属性 包括私有属性
    Ivar *ivar = class_copyIvarList([p class], &count);
    NSLog(@"打印出Person里所有属性(包括私有属性):");
    for (int i=0; i<count; i++) {
        Ivar tmpIvar = ivar[I];
       //通过ivar_getName获取属性名字
        NSString *ivarName = [NSString stringWithUTF8String:ivar_getName(tmpIvar)];
        NSLog(@"%@",ivarName);
        
        if ([ivarName isEqualToString:@"_address"]) {
            //通过object_setIvar修改属性address的值为CN
            object_setIvar(p, tmpIvar, @"CN");
        }
    }

二.动态添加属性

在OC里是不允许直接为一个category添加属性的,但是我们可以通过runtime的方式动态添加,下面是一个为NSString 添加一个name属性的例子

static void *nameKey = &nameKey;
- (void)setName:(NSString *)name {
    objc_setAssociatedObject(self, &nameKey, name, OBJC_ASSOCIATION_COPY);
}

objc_setAssociatedObject 设置关联对象

- (NSString *)name {
    return objc_getAssociatedObject(self, &nameKey);
}

objc_getAssociatedObject 获取关联对象

这样就可以在使用这个category的地方为name这个属性赋值了。

三. 获取类的所有方法

通过class_copyMethodList方法可以获取一个类所有的方法。代码如下:

- (NSMutableArray *)getAllMethods:(Class)class {
    unsigned int count = 0;
    Method *methods = class_copyMethodList(class, &count);
    NSMutableArray *tmp = @[].mutableCopy;
    for (int i=0; i<count; i++) {
        Method method = methods[i];
//        IMP imp = method_getImplementation(method);
        SEL sel = method_getName(method);
        const char *selName = sel_getName(sel);
        const char *encoding = method_getTypeEncoding(method);
        NSString *result = [NSString stringWithFormat:@"方法名:%@, 参数个数:%d, 编码方式:%@",[NSString stringWithUTF8String:selName],method_getNumberOfArguments(method),[NSString stringWithUTF8String:encoding]];
        [tmp addObject:result];
    }
    return tmp;
}

先获取方法列表,再遍历得到Method,再通过method_getName获取SEL ,然后使用sel_getName方法获取到SEL Name。
当然也可以获取到需要传入的参数个数以及参数的编码方式。

四.动态添加方法

      static dispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            class_addMethod([Person class], @selector(eat), (IMP)eatFoods, "v@:");
        });
void eatFoods(id self, SEL _cmd) {
    NSLog(@"eat foods");
}

上述代码,动态的为Person类添加了一个eat的方法, eatFoods是这个方法的实现,也就是他的指针地址

"v@:" 意思是,v 代表无返回值 void,如果是 i 则代表 int;@代表 id sel; : 代表 SEL _cmd;
“v@:@@” 意思是,两个参数的没有返回值。

五. 交换两个方法

以下是交换两个实例方法:

   Method method1 = class_getInstanceMethod(p.class, @selector(personMethod));
    Method method2 = class_getInstanceMethod(p.class, @selector(fetchNameMethod));
    method_exchangeImplementations(method1, method2);

class_getInstanceMethod 的意思是获取实例方法

以下是交换两个类方法:

   Method method3 = class_getClassMethod([Person class], @selector(niceShot));
    Method method4 = class_getClassMethod([Person class], @selector(badShot));
    method_exchangeImplementations(method3, method4);

class_getClassMethod 的意思是获取类方法;

当然两个方法不在同一个类里也是可以互换的,这个只是交换了两个SEL的IMP(指针地址)!

上述只是runtime的一些基础使用方法, 当然它的功能还不仅仅局限于这些,大家可以看看苹果爸爸的官方文档:runtime 官方文档

整理的小Demo: github

相关文章

网友评论

      本文标题:总结几个iOS runtime经常使用的方法

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