宽容他人,放过自己。

使用runtime创建类

Posted on By anchoriteFili

const char *className;
    className = [@"StudentOne" UTF8String];
    Class kclass = objc_getClass(className);
    // 判断该类是否已经存在了,若果存在则返回,不存在就创建
    if (!kclass) {
        Class superClass = [NSObject class];
        kclass = objc_allocateClassPair(superClass, className, 0);
    } else {
        return;
    }
    
    // 为类添加一个NSString类型的成员变量
    class_addIvar(kclass, "_stuName", sizeof(NSString *), 0, "@");
    // 为Student添加一个say:方法
    /**
     第一个参数为类名
     第二个参数为方法名
     第三个参数为函数名
     第四个参数是函数的返回值和参数的类型,v表示的是void, @表示的是id;:表示SEL
     */
    class_addMethod([kclass class], @selector(say:), (IMP)say, "v@:");
    
    // 为Student添加一个stuSex属性 其中T = type C = copy N = nonatomic V = variable name
    // 其中顺序非常重要,必须是 T C N V
    NSString *propertyName = @"stuSex";
    // 如果在添加属性的时候,先添加一个成员变量并进行关联,此时我们是不需要再去添加别的方法也可以使用setValue:forKey:的
    class_addIvar(kclass, [propertyName UTF8String], sizeof(NSString *), 0, "@");
    objc_property_attribute_t type = {"T","@\"NSString\""}; //T = type 是字符串类型
    objc_property_attribute_t ownership = {"C","copy"};
    objc_property_attribute_t backingivar = {"V",[propertyName UTF8String]};
    objc_property_attribute_t attrs[] = {type, ownership,backingivar};
    class_addProperty(kclass, [propertyName UTF8String], attrs, 3);
    
    // 然后注册这个类
    objc_registerClassPair(kclass);
    
    // 创建一个对象进行验证一下
    id p = [[kclass alloc] init];
    [p setValue:@"张三" forKey:@"_stuName"];
    [p setValue:@"男" forKey:@"stuSex"];
    NSLog(@"姓名:%@ 性别:%@",[p valueForKey:@"_stuName"],[p valueForKey:@"stuSex"]);
    [p say:[p valueForKey:@"_stuName"]];
// 1. 创建class
    
    Class kclass = objc_getClass("StudentOne");
    if (!kclass) {
        // 如果class不存在,则创建class
        kclass = objc_allocateClassPair([NSObject class], "StudentOne", 0);
    }
    
    // 给kclass添加变量stuName
    class_addIvar(kclass, "_stuName", sizeof(NSString *), 0, "@");
    
    // 给class添加方法
    class_addMethod(kclass, @selector(say:), (IMP)say, "v@:");
    
    // 给class添加属性stuSex
    class_addIvar(kclass, "stuSex", sizeof(NSString *), 0, "@");
    objc_property_attribute_t type = {"T","@\"NSString\""};
    objc_property_attribute_t ownership = {"C","copy"};
    objc_property_attribute_t Vname = {"V","stuSex"};
    objc_property_attribute_t attrs[] = {type, ownership, Vname};
    class_addProperty(kclass, "stuSex", attrs, 3);
    
    // 注册calss
    objc_registerClassPair(kclass);
    
    // 创建一个对象进行测试
    id p = [[kclass alloc] init];
    [p setValue:@"张三" forKey:@"stuName"];
    [p setValue:@"男" forKey:@"stuSex"];
    NSLog(@"姓名:%@ 性别:%@",[p valueForKey:@"stuName"],[p valueForKey:@"stuSex"]);
    [p say:[p valueForKey:@"stuName"]];
    

// 这个方法实际上没有被调用,但是必须实现,否则不会调用下面函数
- (void)say:(NSString *)aString {
}


// self和_cmd是必须的,在之后可以随意添加其他参数
void say(id self, SEL _cmd, NSString *aString) {
    
    NSLog(@"你好%@",aString);
}