您当前的位置: 首页 > 

white camel

暂无认证

  • 1浏览

    0关注

    442博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

Runtime 一一 runtime使用-动态添加方法和属性

white camel 发布时间:2018-01-26 15:12:35 ,浏览量:1

一、动态添加方法

应用场景: 当一个类的方法非常多,加载类到内存的时候比较耗资源,需要给每个方法生成映射表. 此时可以动态给某个类添加方法

面试题: 是否使用过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

关注
打赏
1661428283
查看更多评论
立即登录/注册

微信扫码登录

0.0363s