objc_property_t Ivar解析

47 篇文章 0 订阅
3 篇文章 0 订阅
/**
 
 cls:指定获取的是哪个类的属性描述信息数组,即objc_property_t类型数组
 outCount:输出指针,指明返回objc_property_t类型数组的大小
 返回objc_property_t类型的数组,每个objc_property_t元素描述一个属性的信息,这个数组中不会包括超类的属性
 objc_property_t * class_copyPropertyList ( Class cls, unsigned int *outCount )
 
 property:指定属性描述信息
 返回属性描述信息中的属性名称的c字符串
 const char * property_getName ( objc_property_t property )
 
 property:指定属性描述信息
 返回属性描述信息中所有特性的c字符串(固定格式,以逗号隔开,通常是T@"类型"开头,V_属性名称结尾的格式),类似于NSObject的description方法返回值
 const char * property_getAttributes ( objc_property_t property );

 property:指定属性描述信息
 outCount:输出指针,指明返回objc_property_attribute_t类型数组的大小
 返回objc_property_attribute_t类型的数组,每个objc_property_attribute_t元素是属性描述信息的一个特性
 objc_property_attribute_t * property_copyAttributeList ( objc_property_t property, unsigned int *outCount );

 返回属性描述信息中指定特性名称为attributeName的c字符串值
 char * property_copyAttributeValue ( objc_property_t property, const char *attributeName )
 
 为类添加新属性
 @param cls 被修改的类
 @param name 新属性的名称
 @param attributes 新属性特性数组
 @param attributeCount 新属性特性数组中元素个数,即特性的个数
 @return YES if the property was added successfully, otherwise  NO
 BOOL class_addProperty(Class cls, const char *name, const objc_property_attribute_t *attributes, unsigned int attributeCount)
 
 
 替换类的一个属性
 @param cls 被修改的类
 @param name 被修改的属性名
 @param attributes 属性新的特性数组
 @param attributeCount 新特性数组中元素个数,即特性的个数
 void class_replaceProperty (Class cls, const char *name, const objc_property_attribute_t*attributes, unsigned int attributeCount);


*/

#import <Foundation/Foundation.h>
#import <objc/message.h>

@interface Job : NSObject

@property (nonatomic, copy) NSString *jobName;

@end

@implementation Job

@end

@interface Person : NSObject{
    NSString *_address;
}

@property (nonatomic, strong) Job *job;
@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) int32_t age;

@end

@implementation Person

-(instancetype)initWithName:(NSString *)name age:(int)age{
    self = [super init];
    if(self){
        
        _address = @"北京";
        (_job = [Job new]).jobName = @"engineer";
        _name = name;
        _age = age;
    }
    
    return self;
}

@end


void printPropertyListInfo(){
    
    Person *person = [Person new];
    Class class = [person class];
    class = [Person class];
    
    //1、获取属性描述信息数组,数组中有count个objc_property_t类型的属性描述信息
    unsigned int count = 0;
    objc_property_t *propertyList = class_copyPropertyList(class, &count);
    
    //遍历打印每个属性描述信息
    for (int i = 0; i < count; i++) {
        objc_property_t property = propertyList[i];
        const char *property_Name = property_getName (property);
        NSLog(@"property_Name = %s", property_Name);
        
        const char *property_Attributes = property_getAttributes (property);
        NSLog(@"property_Attributes = %s", property_Attributes);
        
        unsigned int outCount = 0;
        objc_property_attribute_t *property_AttributeList = property_copyAttributeList (property, &outCount);
        for (int j = 0; j < outCount; j++) {
            objc_property_attribute_t propertyAttribute = property_AttributeList[j];
            NSLog(@"propertyAttribute.name = %s, propertyAttribute.value = %s", propertyAttribute.name, propertyAttribute.value);
            NSLog(@"propertyAttribute.value = %s", property_copyAttributeValue(property, propertyAttribute.name));
        }
        
        NSLog(@"---------------------------------");
    }
}

void addNewProperty(){
    
    Class cls = [Person class];
    
    //组织新属性特性数组
    objc_property_attribute_t attr0 = { "T", "@\"NSDictionary\"" };
    objc_property_attribute_t attr1 = { "&", "" };
    objc_property_attribute_t attr2 = { "N", "" };
    objc_property_attribute_t attr3  = { "V", "_newProperty" };
    objc_property_attribute_t attrs[] = { attr0, attr1, attr2,attr3 };
    
    //添加一个名字为newProperty的NSDictionary类型的属性
    BOOL ret = class_addProperty ( cls, "newProperty", attrs, 4 );
    if (ret) {
        printPropertyListInfo();
    }
}

void replaceProperty(){
    
    Class cls = [Person class];
    
    //组织新的特性数组
    objc_property_attribute_t attr0_ = { "T", "\"NSArray\"" };
    objc_property_attribute_t attr1_ = { "&", "" };
    objc_property_attribute_t attr2_ = { "N", "" };
    objc_property_attribute_t attr3_  = { "V", "_newProperty" };
    objc_property_attribute_t attrs_[] = { attr0_, attr1_, attr2_, attr3_ };
    
    //替换现有的author属性的类型为数组类型
    class_replaceProperty ( cls, "newProperty", attrs_, 4);
    
    printPropertyListInfo();
}

//类的实列变量,注意:变量个数>=属性个数(@property...),因为声明属性时,编译器自动添加实例变量
void printIvarList(){
    
    Person *person = [[Person alloc]initWithName:@"jack" age:26];
    
    unsigned int numIvars = 0;
    //获取类的所有成员变量instance variable
    Ivar * ivars = class_copyIvarList([person class], &numIvars);

    for(int i = 0; i < numIvars; i++) {
        //得到单个的成员变量
        Ivar thisIvar = ivars[i];
        //得到这个成员变量的类型
        const char *type = ivar_getTypeEncoding(thisIvar);
        NSString *stringType =  [NSString stringWithCString:type encoding:NSUTF8StringEncoding];
        /*此处判断非object-c类型时跳过
        if (![stringType hasPrefix:@"@"]) {
            continue;
        }*/
        //得到成员变量名
        NSString *variableName = [NSString stringWithUTF8String:ivar_getName(thisIvar)];
        
        //得到成员变量的值
        id value = [person valueForKey:variableName];
        NSLog(@"类型=%@, 变量名=%@, 变量值=%@", stringType, variableName, value);
        
    }
}

int main(int argc, const char * argv[]) {
    @autoreleasepool {

        printPropertyListInfo();
        printIvarList();
    }
    return 0;

}

下面是swift先关运行时实现

    /*
    func getPropertyListOfPerson() -> Void {
        
        var count: UInt32 = 0
        if let list = class_copyPropertyList(Person.self, &count) {
            print("Person属性个数是:\(count)")
            for i in 0..<count{
                let pty = list[Int(i)]
                let cName = property_getName(pty)
                print("属性名:\(String(utf8String: cName) ?? "")")
            }
            
            free(list)
        }
        
        print("---------------------------------------")
    }
    
    func getIvarListOfPerson() -> Void {
        var count: UInt32 = 0
        if let list = class_copyIvarList(Person.self, &count) {
            print("Person成员变量个数是:\(count)")
            for i in 0..<count{
                let ivar = list[Int(i)]
                if let cName = ivar_getName(ivar){
                    print("实例变量名:\(String(utf8String: cName) ?? "")")
                }
            }
            
            free(list)
        }
        
        print("---------------------------------------")
    }
    
    func geInstancetMethodListOfPerson() -> Void {
        var count: UInt32 = 0
        if let list = class_copyMethodList(Person.self, &count) {
            print("Person实例方法个数是:\(count)")
            for i in 0..<count{
                let method = list[Int(i)]
                let selector = method_getName(method)
                print("实例方法名:\(NSStringFromSelector(selector))")
            }
            
            free(list)
        }
        
        print("---------------------------------------")
        
    }
    
    //To get the class methods of a class, use class_copyMethodList(object_getClass(cls), &count).
    func getClassMethodOfPerson() -> Void {
        var count: UInt32 = 0
        if let list = class_copyMethodList(object_getClass(Person.self), &count) {
            print("Person类方法个数是:\(count)")
            for i in 0..<count{
                let method = list[Int(i)]
                let selector = method_getName(method)
                print("类方法名:\(NSStringFromSelector(selector))")
            }
            
            free(list)
        }
        
        print("---------------------------------------")
    }
    
    func getProtocolListOfPerson() -> Void {
        let p = Person(dic: Dictionary())
        p.proMethodofPerson()
        
        var count: UInt32 = 0
        
        if let list = class_copyProtocolList(object_getClass(Person.self), &count) {
            print("Person遵守的协议个数是:\(count)")
            for i in 0..<count{
                let pro = list[Int(i)]
                let cName = protocol_getName(pro)
                print("协议名:\(String(utf8String: cName) ?? "")")
            }
        }
        
        print("---------------------------------------")
    }
    */


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值