iOS runtime基本用法
本内容为作者原创, 未经允许, 不得用于商业用途
一. 改变实例变量的值 (KVC/MJExtension都是通过这种方式来实现的)
-
添加Person类, 只添加了name属性, 这里跳过实现文件
@interface Person : NSObject @property (copy, nonatomic) NSString *name; @end
-
创建Person类型的实例对象
self.person = [Person new]; self.person.name = @"homer"; NSLog(@"%@", self.person.name);
-
添加方法, 修改name属性的值
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { /// 获取变量个数 unsigned int count = 0; /// 获取所有的实例变量 Ivar *ivar = class_copyIvarList([self.person class], &count); /// 遍历 for (int i = 0; i < count; i++) { /// 实例变量 Ivar var = ivar[i]; /// 实例变量名字 const char *varName = ivar_getName(var); /// 转化一下 NSString *name = [NSString stringWithUTF8String:varName]; if ([name isEqualToString:@"_name"]) { object_setIvar(self.person, var, @"lynn"); break; } } NSLog(@"%@", self.person.name); }
-
控制台输出,显示修改成功
[图片上传失败...(image-da361-1523429930821)]
二. 方法交换(常用来hock/埋点等)
-
在Person中新增2个方法
- (void)firstMethod { NSLog(@"1st method has been called"); } - (void)secondMethod { NSLog(@"2nd method has been called"); }
-
实现方法交换
- (void)exchangeMethod { /// 获取方法 Method m1 = class_getInstanceMethod([self.person class], @selector(firstMethod)); Method m2 = class_getInstanceMethod([self.person class], @selector(secondMethod)); /// 交换方法 method_exchangeImplementations(m1, m2); }
-
分别在交换前后调用
firstMethod
和secondMethod
, 查看控制台输出[图片上传失败...(image-a492d2-1523429930821)]
三. 动态添加方法
-
添加方法
- (void)addMethod { /// "v@:@" v表示void, @表示id类型, :表示SEL class_addMethod([self.person class], @selector(run:), (IMP)run, "v@:@"); } void run(id self, SEL _cmd, NSString *miles) { NSLog(@"Tome run %@ miles", miles); } - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { [self addMethod]; if ([self.person respondsToSelector:@selector(run:)]) { [self.person performSelector:@selector(run:) withObject:@"1"]; } else { NSLog(@"Method named run: is not been defined!"); } }
-
查看输出
[图片上传失败...(image-9484c4-1523429930821)]
四. 使用关联属性给类型添加属性
-
给Person类添加nick属性
@property (copy, nonatomic) NSString *name; - (void)firstMethod { NSLog(@"1st method has been called"); } - (void)secondMethod { NSLog(@"2nd method has been called"); }
-
调用属性
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event { self.person.nick = @"Homer Lynn"; NSLog(@"%@", self.person.nick); }
-
查看输出
[图片上传失败...(image-7b5e8c-1523429930821)]