Runtime

前提工作导入#import <objc/message.h>

runtime的使用场景:  1.  消息机制 ; 2. 交换方法  ;  3.动态添加方法

; 4. 动态添加属性;

任何方法的调用本质: 就是发送一个消息,用runtime发送消息,

*  //类方法的本质: 类对象调用[NSObject class]

1.  消息机制 :

*  1. 不得不用消息机制, 可以帮助开发者调用私有方法;

*  2. 修改系统方法的实现的时候

//id : 谁发送消息

//SEL : 发送什么消息

//Xcod6 : 使用objc_msgSend() 有参数提示, xcod6之后没有参数提示(打开提示build settings --> 搜索msg, --> 设置为No),原因是苹果不想让开发者了解runtime的底层实现,

//最终代码需要把当前代码重新编译,用xcod,  clang命令 ----->     clang -rewrite-objc main.m

id objc = objc_msgSend([NSObject class], @selector(alloc)); //相当于 id objc = [NSObject alloc]

objc = objc_msgSend(objc , @selector(init)); //相当于  objc =[objc init];

创建一个Person类

#import@interface Person : NSObject

- (void)eat;

- (void)run:(NSInteger)metre;

@end

#import "Person.h"#import@implementation Person

- (void)eat{

NSLog(@"吃");

}

- (void)run:(NSInteger)metre{

NSLog(@"metre = %ld",(long)metre);

}

@end

Person * p = objc_msgSend(objc_getClass("Person"),sel_registerName("alloc")); //相当于 Person * p  =[Person alloc];

p =  objc_msgSend(p,  sel_registerName("init")); // 相当于p = [p init];

//调用eat方法;

如果将eat方法注释掉 用OC的[p eat]会报错,只能用runtime的方法调用私有方法, runtime底层会自己查找eat方法

objc_msgSend(p, @selector(eat)); //不带参数 [p eat];

objc_msgSend(p, @selector(run:),20); //带参数的  [p run:20];

//方法的调用流程:(以eat方法为列)

//怎么调用(eat)方法: -->对象方法: 保存到类对象的方法列表(MethodList)里面 ;  类方法: 保存在元类中的方法列表(MethodList)中

// 1. 通过isa指针到对应的类中查找,

// 2. 把方法名注册为方法编号(_cmd)

// 3. 根据方法编号去查找对应的方法(而不是根据方法名去查找对应的方法)

// 4. 找到的只是最终函数实现地址,根据地址到方法区(内存)调用对应的函数(方法的实现不是保存子在类里面而是在内存的方法区)


2. runtime(交换方法):

*  需求: 每次UIImage加载图片, 告诉是否加载成功 (给系统的imageNamed添加方法)

// 给系统的imageNamed添加方法 : 1. 给系统的方法添加分类 2. 自己实现带有扩展功能的方法 3 . 交换方法, 交换一次就可以了

*  1. 自定义UIImage ( 每次使用都需要导入自定义的类, 2 .项目太大,没办法实现  )

*  2. 分类 (分类中尽最好不要重写系统的方法, 一旦重写就会把系统的方法实现干掉)

#import@interface UIImage (category)

+ (UIImage *)my_imageNamed:(NSString *)name;

@end

#import "UIImage+category.h"#import@implementation UIImage (category)

//把类加载进内存的时候调用, 只会调用一次

+ (void)load{  // swift中只能用initialize方法

//获取imageNamed方法:

Method imageNameMethod = class_getClassMethod(self, @selector(imageNamed:));

//获取my_imageNamed方法:

Method my_imageNamedMethod = class_getClassMethod(self, @selector(my_imageNamed:));

// 交换方法: runtime

method_exchangeImplementations(imageNameMethod, my_imageNamedMethod);

}

//

+ (UIImage *)my_imageNamed:(NSString *)name{

UIImage * image = [UIImage my_imageNamed:name];

if (image) {

NSLog(@"加载成功");

}else{

NSLog(@"加载失败");

}

return image;

}

- (void)viewDidLoad {

[super viewDidLoad];

UIImage * image = [UIImage imageNamed:@"1.png"];//调用imageNamed时候 ==> 调用my_imageNamed方法

}

3.动态添加方法

runtime(动态添加方法): OC是懒加载机制,只要一个方法实现了, 就会马上添加到方法列表中.

performSelector什么使用, 动态添加方法的时候使用, 为什么动态的添加方法(对收费版的APP需要用到runtime动态添加方法)

创建Car类

#import@interface Car : NSObject

@property (assign, nonatomic) NSInteger  tel;

@property (strong, nonatomic) NSString * sex;

@end

#import "Car.h"#import@implementation Car

//方法 (函数)

void abc(id self, SEL _cmd) {

NSLog(@"红旗");

}

//任何方法默认都有两个隐式参数: self , _cmd

//只要一个对象调用了一个未实现的方法就会调用这个方法,进行处理

// 作用: 动态添加方法, 处理未实现的方法

+ (BOOL)resolveInstanceMethod:(SEL)sel{

if (sel == NSSelectorFromString(@"name")) {

/**

*  @param Class : 给那个类添加方法

*  @param SEL :  添加那个方法

*  @param IMP :  方法实现 --> 函数 --> 函数入口 --> 函数名

*  @param type : 方法类型

*  @return

*/

class_addMethod(self, sel, (IMP)abc, "v@:");

return YES;

}

return [super resolveInstanceMethod:sel];

}

@end

- (void)viewDidLoad {

[super viewDidLoad];

Car * car = [[Car alloc]init];

[car performSelector:@selector(name)];

}



4. 动态添加属性

Runtime(动态添加属性): 什么情况下需要动态添加属性(给系统的类添加属性的时候, 可以用runtime动态添加属性的方法)

*  需求:让一个NSObject 类保存一个字符串

*  动态添加属性的本质: 让某个属性与对象产生关联

*  runtime一般都是针对系统的类,

#import  <Foundation/Foundation.h>

@interface NSObject (propertyCategory)

//@property在分类里面的只会产生get,set方法的声明,不会生成实现,也不会生成下划线成员属性

@property NSString * name;

@end

#import "NSObject+propertyCategory.h"

#import@implementation NSObject (propertyCategory)

- (void)setName:(NSString *)name{//让这个字符串与当前对象产生联系

// object : 给哪个对象添加属性   ;   key : 属性名称   ; value : 属性值    policy : 保存策略

objc_setAssociatedObject(self, @"name", name, OBJC_ASSOCIATION_RETAIN_NONATOMIC);}

- (NSString *)name{

return objc_getAssociatedObject(self, @"name");

}

@end

- (void)viewDidLoad {

[super viewDidLoad];

NSObject * objc = [[NSObject alloc]init];

objc.name = @"789";//动态给NSObject添加name属性

NSLog(@"%@",objc.name);

}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,884评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,347评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,435评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,509评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,611评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,837评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,987评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,730评论 0 267
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,194评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,525评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,664评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,334评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,944评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,764评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,997评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,389评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,554评论 2 349

推荐阅读更多精彩内容

  • 对于从事 iOS 开发人员来说,所有的人都会答出【runtime 是运行时】什么情况下用runtime?大部分人能...
    梦夜繁星阅读 3,700评论 7 64
  • 1️⃣runtime介绍: runtime是一套比较底层的纯C语言API, 包含了很多底层的C语言API。在我们平...
    CoderZS阅读 1,056评论 0 7
  • 导读:11、12月注定是不太平的月份,好多小型互联网创业公司都突然崩塌,最近一个朋友跟我抱怨道,说终于感受到了互联...
    柳骏阅读 9,675评论 11 167
  • 1.runtime简介 因为Objc是一门动态语言,所以它总是想办法把一些决定工作从编译连接推迟到运行时。也就是说...
    杰哥ios工程狮阅读 4,202评论 0 47
  • 晨起慢跑 午后休憩 夜临读书 有梦想 能吃苦 知进退 该进取的年纪 不荒废 该坚持的方向 不退缩 该获取的储备 不...
    小溪0903阅读 186评论 0 0