iOS Runtime之动态创建类
场景
当遇到一些在App中没有创建过的类,想要动态添加时,可以使用。
例如:云端控制点击响应页面跳转事件。
应用
动态创建类,开辟内存
objc_allocateClassPair
可以动态创建类,指示它的父类。
class_addIvar
可以给类添加成员变量。
objc_registerClassPair
注册一个已经创建的类,在添加成员变量后使用。
class_addMethod
给类添加方法。
实现
#import "JX_DynamicClassViewController.h"
#import <objc/runtime.h>
@interface JX_DynamicClassViewController ()
@end
@implementation JX_DynamicClassViewController
- (void)viewDidLoad {
[super viewDidLoad];
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
[btn setTitle:@"Go" forState:UIControlStateNormal];
[btn setBackgroundColor:[UIColor blackColor]];
[btn setFrame:CGRectMake(10, 100, 200, 40)];
[btn addTarget:self action:@selector(newPageClick) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btn];
}
// 按钮点击
- (void)newPageClick {
// 动态创建一个vc,开辟内存
Class cls = objc_allocateClassPair(UIViewController.class, "JX_DynamicVC", 0);
// 给vc添加变量
class_addIvar(cls, "bgColor", sizeof(UIColor *), log2(sizeof(UIColor *)), @encode(UIColor *));
class_addIvar(cls, "text", sizeof(NSString *), log2(sizeof(NSString *)), @encode(NSString *));
objc_registerClassPair(cls);
// 给vc添加方法
IMP vdl_imp = class_getMethodImplementation([self class], @selector(viewDidLoad_dynamicImp));
class_addMethod(cls, @selector(viewDidLoad), vdl_imp, "v16@0:8");
// 方法签名不想手写,也可以通过方法获取
// const char *types = method_getTypeEncoding(class_getInstanceMethod([self class], @selector(viewDidLoad_dynamicImp)));
// class_addMethod(cls, @selector(viewDidLoad), vdl_imp, types);
// 初始化新类对象
id newVC = [[cls alloc] init];
[newVC setValue:[UIColor greenColor] forKey:@"bgColor"];
[newVC setValue:@"this is dynamic vc" forKey:@"text"];
[self presentViewController:newVC animated:YES completion:^{
}];
}
// 动态创建vc的viewDidLoad方法实现
- (void)viewDidLoad_dynamicImp {
[super viewDidLoad];
// 这里方法因为添加给newVC,因此self是newVC
[self setValue:[self valueForKey:@"bgColor"] forKeyPath:@"view.backgroundColor"];
// 添加标签
UILabel *lab = [[UILabel alloc] initWithFrame:CGRectMake(10, 200, 200, 40)];
[[self valueForKey:@"view"] addSubview:lab];
lab.text = [self valueForKey:@"text"];
}
@end
其他
没有其他了。