OC 反射-->动态创建类

2018-02-16 19:41:43来源:cnblogs.com作者:Harely人点击

分享

创建Class

 1 - (Class) createNewClass { 2     const char * className; 3     className = [@"Student" UTF8String]; 4     Class kclass = objc_getClass(className); 5     //判断此类是否已经存在,如果存在则返回,不存在就创建 6     if (!kclass) 7     { 8         Class superClass = [NSObject class]; 9         kclass = objc_allocateClassPair(superClass, className, 0);10     }11     return kclass;12 }

 注册类

1  Class newClass = [self createNewClass];2  id instanceObjects = [[newClass alloc] init];3  NSLog(@"注册后的类实例化对象:%@", instanceObjects);

打印结果:


添加成员变量

1 //添加成员变量2 - (void) addNewVariable:(Class) newClass {3     class_addIvar(newClass, "_stuName", sizeof(NSString *), 0, "@");4 }

 注意:这个方法的调用要在objc_allocateClassPair方法之后和注册类objc_registerClassPair方法之前调用,否则没法动态添加成员变量。

这是因为方法和属性并不“属于”类实例,而成员变量“属于”类实例。我们所说的“类实例”概念,指的是一块内存区域,包含了isa指针和所有的成员变量。所以假如允许动态修改类成员变量布局,已经创建出的类实例就不符合类定义了,变成了无效对象。但方法定义是在objc_class中管理的,不管如何增删类方法,都不影响类实例的内存布局,已经创建出的类实例仍然可正常使用。

获取Class的成员变量名

 1 //    获取类的成员变量名 2 - (NSArray *)getVariableNamesByObject:(id)object 3 { 4     unsigned int numIvars = 0; 5 //    获取类的所有成员变量 6     Ivar * ivars = class_copyIvarList([object class], &numIvars); 7 //    定义一个数组来接收获取的属性名 8     NSMutableArray *nameArray = [[NSMutableArray alloc] initWithCapacity:numIvars]; 9     for(int i = 0; i < numIvars; i++) {10 //        得到单个的成员变量11         Ivar thisIvar = ivars[i];12 //        得到这个成员变量的类型13         const char *type = ivar_getTypeEncoding(thisIvar);14         NSString *stringType =  [NSString stringWithCString:type encoding:NSUTF8StringEncoding];15 //        此处判断非object-c类型时跳过16         if (![stringType hasPrefix:@"@"]) {17             continue;18         }19 //        得到成员变量名20         NSString *variableName = [NSString stringWithUTF8String:ivar_getName(thisIvar)];21         [nameArray addObject:variableName];22         23 //        这个函数可以得到成员变量的值24 //        object_getIvar(object, thisIvar)25         26     }27     free(ivars);28     return nameArray;29 }

调用以后,结果为:


创建方法

第一个参数为类名,第二个参数为方法名,第三个参数是函数名,第四个参数是函数的返回值和参数的类型,v表是void,@表示id,:表示SEL。更多多定义参考:SELECTOR

1    class_addMethod([kclass class], @selector(say:), (IMP)say, "v@:");

需要实现,这个方法


添加属性

1 //添加一个属性2 - (void) addProperties:(Class) newClass {3     NSString *propertyName = @"stuSex";4     objc_property_attribute_t type = { "T", "@/"NSString/"" };5     objc_property_attribute_t ownership = { "C", "copy" };6     objc_property_attribute_t backingivar  = { "V", [propertyName UTF8String]};7     objc_property_attribute_t attrs[] = { type, ownership, backingivar };8     BOOL isOk=class_addProperty(newClass, [propertyName UTF8String], attrs, 3);9 }

查看属性

 1 //    获取类的所有属性名 2 - (NSArray*)getPropertieNamesByObject:(id)object 3 { 4      5     unsigned int outCount, i; 6      7 //    获取注册类的属性列表,第一个参数是类,第二个参数是接收类属性数目的变量 8     objc_property_t *properties = class_copyPropertyList([object class], &outCount);  9 //    定义一个数组来接收获取的属性名10     NSMutableArray *nameArray = [[NSMutableArray alloc] initWithCapacity:outCount];11     for (i = 0; i < outCount; i++) {12 //        通过循环来获取单个属性13         objc_property_t property = properties[i];14 //        取得属性名15         NSString *propertyName = [[NSString alloc] initWithCString:property_getName(property) encoding:NSUTF8StringEncoding];16 //        将得到的属性名放入数组中17         [nameArray addObject:propertyName];18         19     }20     free(properties);21     return nameArray;22 }

打印结果:


相关文章

    无相关信息

最新文章

123

最新摄影

闪念基因

微信扫一扫

第七城市微信公众平台