iOS高级开发 RunTime机制讲解二

下载DEMO:https://github.com/sleepsheep/RunTimeDemo02
1、创建一个single application;
2、创建两个类:CustomClass、CustomClassOther

@interface CustomClass : NSObject

@property (nonatomic, copy) NSString *varTest1;
@property (nonatomic, copy) NSString *varTest2;
@property (nonatomic, copy) NSString *varTest3;

- (void)testFun1;

@end

@implementation CustomClass

- (void)testFun1 {
    NSLog(@"testFun1");
}

@end
@implementation CustomClassOther

- (void)testFun2 {
    NSLog(@"testFUn2");
}

@end

@interface CustomClassOther : NSObject

@property (nonatomic, assign) int varTest2;

- (void)testFun2;

@end

3、创建一个测试类ClassPropertyViewController

@class CustomClass;
@interface ClassPropertyViewController : UIViewController

@property (nonatomic, assign) float myFloat;
@property (nonatomic, strong) CustomClass *allobj;

@end

方法讲解:

1、获取类的所有方法
Method *class_copyMethodsList(class cls, unsigned int *count)
参数说明:1、class cls : 方法所在的类 2、unsigned int 方法的总数
返回值:返回一个 runtime内部定义的一个方法数组。
2、获取一个类的所有的属性
objc_property_t *class_copyPropertyList(Class cls, unsigned int *outCount)
参数说明:1、class cls : 属性所在的类 2、unsigned int 属性的数目
返回值:返回一个Char字符数组。
3、获取类的属性变量的值
Ivar object_getInstanceVariable(id obj, const char *name, void **outValue)
参数说明:1、id obj : 属性所在的类的对象 2、要获取的变量的名称 3、void * *outValue 外部接收属性值得变量
返回值:IVar RunTime中用来表示实例变量
4、设置类的属性变量的值
Ivar object_setInstanceVariable(id obj, const char *name, void *value)
参数说明:1、id obj : 待设置的类,属性所在的类 2、const char *name : 待设置的属性的名称 3、void *value : value 数形变量的新值
返回值:Ivar Runtime中用来表示实例变量(官方解释:A pointer to the Ivar data structure that defines the type and name of the instance variable specified by name. )。
5、判断类的某个属性的类型
const char * ivar_getTypeEncoding(Ivar var)
参数说明:1、Ivar var : runtime实例变量的结构体name 、type 、 offset。
6、通过属性的值来获取属性的名字
思路:1、获取一个类的所有的属性 2、遍历这些属性,依次去取这些属性的值 3、判断这些值和传入的属性的值是否相同 4、如果相同就获取Ivar的名字。

代码如下:

- (instancetype)init
{
    self = [super init];
    if (self) {
        _myFloat = 2.34f;
    }
    return self;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
//    [self getClassAllMethod];
    
//    [self propertyNameList];
    
//    [self getInstanceVar];
    
    [self setInstanceVar];
    
//    [self getVarType];
    
//    _allobj = [CustomClass new];
//    _allobj.varTest1 = @"test1";
//    _allobj.varTest2 = @"test2";
//    _allobj.varTest3 = @"test3";
//    
//    NSString *var = [self nameOfInstance:@"test2"];
//    NSLog(@"%@", var);// _varTest2
    
}

// 6、通过属性的值来获取属性的名字(反射机制)
- (NSString *)nameOfInstance:(id)instance {
    unsigned int numlvars = 0;
    NSString *key = nil;
    
    Ivar *vars = class_copyIvarList([CustomClass class], &numlvars);//1、获取一个类的所有的属性
    
    for (int i = 0; i < numlvars; i++) {
        Ivar thisVar = vars[i];//2、遍历这些属性,依次去取这些属性的值
        
        const char *type_encoding = ivar_getTypeEncoding(thisVar);
        NSString *type = [NSString stringWithCString:type_encoding encoding:NSUTF8StringEncoding];
        
        if (![type hasPrefix:@"@"]) {//
            continue;
        }
        
        if ((object_getIvar(_allobj, thisVar)) == instance) {//object_getIvar 是获取属性的值//3、判断这些值和传入的属性的值是否相同
            key = [NSString stringWithUTF8String:ivar_getName(thisVar)];//4、如果相同就获取Ivar的名字
            break;
        }
    }
    
    free(vars);
    return key;
}

//5、判断类的某个属性的类型
- (void)getVarType {
    CustomClass *obj = [CustomClass new];
    Ivar var = class_getInstanceVariable(object_getClass(obj), "_varTest1");
    const char *type_encoding = ivar_getTypeEncoding(var);
    NSString *type = [NSString stringWithCString:type_encoding encoding:NSUTF8StringEncoding];
    NSLog(@"%@", type);//@"NSString"
    
}

// 4、设置类的属性变量的值
- (void)setInstanceVar {
    float newValue = 10.0f;
    unsigned int addr = (unsigned int)&newValue;
    object_setInstanceVariable(self, "_myFloat", *(float **)addr);//这里报了个错 不知道如何解 求解
    NSLog(@"%f", _myFloat);

}

// 3、获取类的属性变量的值
- (void)getInstanceVar {
    float myFloatValue;
    object_getInstanceVariable(self, "_myFloat", (void *)&myFloatValue);
    NSLog(@"%f", myFloatValue);//2.340000
}

//2、获取一个类的所有的属性
- (void)propertyNameList {
    u_int count;
    objc_property_t *properties = class_copyPropertyList([UIViewController class], &count);
    
    for (int i = 0; i < count; i++) {
        const char *propertyName = property_getName(properties[i]);
        NSString *name = [NSString stringWithCString:propertyName encoding:NSUTF8StringEncoding];
        NSLog(@"i = %d methodName = %@", i, name);//打印内容太多 == 运行查看
    }
}

// 1、获取类的所有方法
- (void)getClassAllMethod {
    u_int count;
    Method *methods = class_copyMethodList([UIViewController class], &count);
    
    for (int i = 0; i < count; i++) {
        SEL sel = method_getName(methods[i]);
        NSString *name = [NSString stringWithCString:sel_getName(sel) encoding:NSUTF8StringEncoding];
        NSLog(@"i = %d methodName = %@", i, name);//打印内容太多 == 运行查看
    }
}

你可能感兴趣的:(iOS高级开发 RunTime机制讲解二)