runtime 系列-2获取类的所有特征(属性,实例变量,方法)

在本文中,主要是通过 runtime 去过去对象的特性,比如属性,实例变量和方法等,其中主要使用到的runtime 函数是.
1).class_copyPropertyList—获取一个类的所有属性,如果没有属性count就为0
2).property_getName—获取属性名称
3).objc_property_t—接收class_copyPropertyList返回的属性地址指针
4).free—使用free函数来释放objc_property_t指针数组内存
5).class_copyIvarList—通过传入一个类,获取这个类所有的实例变量
6).ivar_getName—通过传入数组中的一个实例变量元素返回一个实例变量的字符
7).class_copyMethodList—通过传入一个类,获取这个类所有的方法
8).method_getName—-通过传入数组中的一个实例变量元素返回一个方法名称,为一个 SEL方法选择器
9).sel_getName—通过传入的 SEL方法名称,返回方法字符
10).method_getNumberOfArguments—返回由方法接受的参数个数。

上面是在获取属性,实例变量,方法使用到的 runtime 函数,下面通过代码来展示使用方法

People.h 文件

#import <Foundation/Foundation.h>

@interface People : NSObject{
    /**
     *  添加两个实例变量
     */
    NSString *_occupation;//职业
    NSString *_nationality;//国籍
}
/**
 *  添加两个属性
 */
@property (nonatomic,copy)NSString *name;
@property (nonatomic,assign)NSInteger age;

/**
 *  属性方法
 */

- (NSDictionary *)allProperties;
- (NSDictionary *)allIvars;
- (NSDictionary *)allMethods;
@end

People.m文件

#import "People.h"
#import <objc/runtime.h>
@implementation People
- (NSDictionary *)allProperties {
    unsigned int count = 0;
    /**
     *  获取一个类的所有属性,如果没有属性count就为0
     *
     *  @param cls#>      类 description#>
     *  @param outCount#> 传入一个地址,将返回一个 Int 型的值到该地址 description#>
     *
     *  @return 返回所有属性的一个 c 语言指针,指针指向的是一个数组
     */
    objc_property_t *properties = class_copyPropertyList([self class], &count);
    NSMutableDictionary *resultDict = [@{} mutableCopy];
    for (NSUInteger i = 0 ; i < count; i++) {
        /**
         *  通过class_copyPropertyList获取所有属性,取到其中的一个
         *
         *  @param properties 传入一个属性
         *
         *  @return 返回该属性的字符
         */
        const char *propertyName = property_getName(properties[i]);
        //将返回的字符进行 UTF8编码
        NSString *name = [NSString stringWithUTF8String:propertyName];
        //KVC里面的方法,目的是通过属性获取其值
        id propertyValue = [self valueForKey:name];
        if (propertyValue) {
            resultDict[name] = propertyValue;
        }else {
            resultDict[name] = @"字典的key对应的value不能为nil哦!";
        }
    }
    // 这里properties是一个数组指针,我们需要使用free函数来释放内存。
    free(properties);
    return resultDict;
}

- (NSDictionary *)allIvars {
    unsigned int count = 0;
    /**
     *  通过传入一个类,获取这个类所有的实例变量
     *  第一个参数 : 传入一个类
     *  第二个参数 : 传入一个地址,返回一个 Int 型的值到这个地址
     *  返回一个包含所有实例变量的指针
     */
    Ivar *ivar = class_copyIvarList([self class], &count);
    NSMutableDictionary *resultDict = [@{} mutableCopy];
    for (NSUInteger i = 0 ;i < count;i++) {
        /**
         *  遍历实例变量指针中的其中一个实例变量
         *
         *  @param ivar 传入一个实例变量
         *
         *  @return 返回一个实例变量的字符
         */
        const char *ivarName = ivar_getName(ivar[i]);
        NSString *name = [NSString stringWithUTF8String:ivarName];
        id valueName = [self valueForKey:name];
        if (valueName) {
            resultDict[name] = valueName;
        }else {
            resultDict[name] = @"字典的key对应的value不能为nil哦!";
        }
    }
    free(ivar);
    return resultDict;
}

- (NSDictionary *)allMethods {
    unsigned int count = 0;
    NSMutableDictionary *resultDict = [@{} mutableCopy];

    Method *methods = class_copyMethodList([self class], &count);
    for (NSUInteger i = 0; i<count; i++) {
        // 获取方法名称
        SEL methodSEL = method_getName(methods[i]);
        const char *methodName = sel_getName(methodSEL);
        NSString *name = [NSString stringWithUTF8String:methodName];
        /**
         *  返回由方法接受的参数个数。
         *  包含给定的方法接受的参数个数的整数。
         */
        int arguments = method_getNumberOfArguments(methods[i]);
        NSLog(@"%zd",arguments);
        resultDict[name] = @(arguments - 2);
    }
    free(methods);
    return resultDict;
}
@end

main.m文件


#import <Foundation/Foundation.h>
#import "People.h"
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...

        People *teacherChang = [[People alloc]init];
        teacherChang.name = @"苍井空";
        teacherChang.age = 18;
        [teacherChang setValue:@"老师" forKey:@"occupation"];
        NSDictionary *propertyResultDict = [teacherChang allProperties];
        for (NSString *propertuResultString in propertyResultDict.allKeys) {
             NSLog(@"propertyName:%@, propertyValue:%@",propertuResultString, propertyResultDict[propertuResultString]);
        }

        NSDictionary *ivarResultDic = [teacherChang allIvars];
        for (NSString *ivarName in ivarResultDic.allKeys) {
            NSLog(@"ivarName:%@, ivarValue:%@",ivarName, ivarResultDic[ivarName]);
        }

        NSDictionary *methodResultDic = [teacherChang allMethods];
        for (NSString *methodName in methodResultDic.allKeys) {
            NSLog(@"methodName:%@, argumentsCount:%@", methodName, methodResultDic[methodName]);
        }
    }
    return 0;
}

通过以上的代码,就成功得获取到了 People 对象的所有属性,实例变量,以及方法,学会这个技能,在开发中可以方便更多!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值