一、动态添加方法
应用场景: 当一个类的方法非常多,加载类到内存的时候比较耗资源,需要给每个方法生成映射表. 此时可以动态给某个类添加方法
面试题: 是否使用过performSelector, 其实就是想问你有没有动态添加过方法
知识点:
1. 所有的方法,默认都有 id self, SEL _cmd 这两个隐式参数. _cmd表示当前方法的方法编号
2. + (BOOL)resolveInstanceMethod:(SEL)sel 用来判断,未实现的方法是否是我们想要动态添加的方法
3. 动态添加 class_addMethod(arg1, arg2, arg3, arg4);
#import "ViewController.h"
#import "Person.h"
@interface ViewController ()
@end
@implementation ViewController
/*
动态添加方法:
开发中的使用场景: 如果一个类方法非常多,加载类到内存的时候比较消耗资源,需要给每个方法生成映射表,可以动态给某个类添加方法
面试题: 是否使用过performSelector, 其实主要想问你有没有动态添加过方法
*/
- (void)viewDidLoad {
[super viewDidLoad];
Person *p = [[Person alloc] init];
// [p performSelector:@selector(eat)];
[p performSelector:@selector(run:) withObject:@"ZY" withObject:@20];
}
@end
#import "Person.h"
#import
@implementation Person
// 所有的方法.默认都有self, _cmd 这两个隐式参数
// _cmd 表示当前方法的方法编号
void eatFood(id self, SEL _cmd)
{
NSLog(@"吃食物!");
}
void runPace(id self, SEL _cmd, NSString *name, NSNumber *meter)
{
NSLog(@"我叫%@,我今年%@,我在?",name,meter);
// _cmd 表示当前方法的方法编号
NSLog(@"%@",NSStringFromSelector(_cmd));
}
// 当一个对象调用未实现的方法,会调用这个方法来处理,并且会把对应的方法列表传过来
// 可以用来判断,未实现的方法是否是我们想要动态添加的方法
+ (BOOL)resolveInstanceMethod:(SEL)sel
{
// if ([NSStringFromSelector(sel) isEqualToString:@"eat"]){
if (sel == NSSelectorFromString(@"eat")) {
/*
param1: class 给哪个类添加方法
param2: SEL 添加哪个方法
param3: IMP: 方法实现(在方法区) => 函数 => 函数入口 => 函数名
param4: type: 方法类型
*/
class_addMethod(self, sel, (IMP)eatFood, "v@:");
return YES;
}
if ([NSStringFromSelector(sel) isEqualToString:@"run:"]) {
class_addMethod(self, sel, (IMP)runPace, "v@:@@");
return YES;
}
return [super resolveInstanceMethod:sel];
}
二、动态添加属性
应用场景: 给系统的类增加属性的时候,可以使用runtime动态添加属性.
本质: 动态添加属性,就是让某个属性与对象产生关联
runtime一般针对系统的类
需求: 把基类NSObject类,添加一个name字符串属性
步骤:
1. 给系统自带的NSObject属性添加分类
2. 在分类中声明name属性,在分类中@property NSString *name; 只会生成get,set方法的声明,并且不会生成私有属性_name.
本质不会生成成员属性,而是提供get,set方法声明,供外界调用
3. 在分类中实现get,set方法
4. set方法实现,把传递的值给对象关联
5. get方法实现,把关联的值取出来传出去
#import "ViewController.h"
#import "NSObject+Property.h"
#import "Person.h"
@interface ViewController ()
@end
@implementation ViewController
// 动态添加属性
// 开发场景:
// 给系统的类添加属性的时候,可以使用runtime动态添加属性方法
// 本质:动态添加属性,就是让某个属性与对象产生关联
// runtime一般都是针对系统的类
/*
需求:让一个NSObject类 保存一个name字符串属性
动态添加NSObject属性的步骤
1.给系统自带的NSObject添加分类
2.在分类中声明属性的get,set方法,本质并不是真的生成成员属性,而是提供get,set方法,供外界获取
3.在分类实现get,set方法
4.set方法实现,把传递的值给对象关联。
5.get方法实现,把关联的值取出来传出去
*/
- (void)viewDidLoad {
[super viewDidLoad];
NSObject *objc = [[NSObject alloc] init];
objc.name = @"ZY";
NSLog(@"%@",objc.name);
Person *p = [[Person alloc] init];
p.name = @"GZY";
}
@end
分类NSObject+Property:
#import
@interface NSObject (Property)
// @property分类: 只会生成get,set方法声明,不会生成方法实现,并且不会生成_name私有属性
@property NSString *name;
@end
#import "NSObject+Property.h"
#import
@implementation NSObject (Property)
// 属性名称
static const char *key = "name";
// set方法
- (void)setName:(NSString *)name
{
// 让这个字符串与当前对象产生联系
/*
param1:object:给哪个对象添加属性
param2:key:属性名称
param3:value:属性值
param4:policy:保存策略
*/
objc_setAssociatedObject(self, key, name, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
// get 方法
- (NSString *)name
{
return objc_getAssociatedObject(self, key);
}
@end