runtime(消息机制)

简介: runtime(消息机制)

一.runtime简介



  • Runtime简称运行时,OC就是运行时机制,也就是在运行的时候的一些机制,其中最主要的是消息机制.
  • 对于C语言,函数的调用在编译的时候会决定调用哪个函数.
  • 对于oc的函数,属于动态调用过程,在编译的时候并不能真正调用哪个函数,只有在真正运行的时候才会根据函数的名称找到对应的函数来调用.
  • 事实证明:
  • (1).在编译阶段,oc可以调用任何函数,即使这个函数并未实现,只要声明过就不会报错.
  • (2).在编译阶段,c语言调用未实现的函数就会报错


OC:运行时机制,消息机制是运行时机制最重要的机制


消息机制:任何方法调用,本质都是发送消息


二.runtime的使用



运行时,发送消息,谁做事请就拿谁


xcode5 之后,苹果不建议使用底层的方法


** xcode5之后,使用运行时**(使用运行时的原因)


(1).方法调用的本质,就是让对象发送消息.objc_msgSend只有对象才能发消息,因此以objc开头,使用消息机制前提,必须导入#import <objc/message.h>

(2).Build Setting -> 搜索msg -> 设置属性为NO


image.png

(3).真正的使用


在外面我定义了一个Person的类,方法都进行了实现


image.png

消息机制调用对象方法:(调用的是多个参数的)

objc_msgSend(person, @selector(run:sdd:),25,@"名字");

额外提一句:类方法的调用:本质是把类名转化为类对象

//类方法的调用:本质是把类名转化为类对象
1.[Person eat];
2.[[Person class]performSelector:@selector(eat)];
3.
id personClass = [Person class];
[personClass performSelector:@selector(eat)];

类方法运行机制的调用:

objc_msgSend([Person class], @selector(eat));


如果用一张图来表示的话就是下面的:


image.png


1.先用对象 -> 2.performSelector -> 3.@selector(方法:类似键)+有参数就添加 ->


4.这个对象的方法库里面寻找方法 -> 5.找到这个方法来调用


三.runtime交换方法



UIImage+Image.h


#import <UIKit/UIKit.h>

@interface UIImage (Image)

+(__kindof UIImage *) jk_imageNamed:(NSString *)imageName;
@end


UIImage+Image.m


#import "UIImage+Image.h"

#import <objc/message.h>

@implementation UIImage (Image)

//交换的方法实现,方法都定义在类里面

/**
 *  Class : 获取哪个类方法
 *  SEL : 获取方法编号,根据SEL就能去对应的类找方法
 */
//获取类方法
//class_getClassMethod(<#__unsafe_unretained Class cls#>, <#SEL name#>)
//获取对象方法
//class_getInstanceMethod(<#__unsafe_unretained Class cls#>, <#SEL name#>)
+(void)load
{
//交换方法实现
//获取类方法
Method imageMethod = class_getClassMethod([UIImage class], @selector(imageNamed:));
Method jk_imageMethod = class_getClassMethod([UIImage class], @selector(jk_imageNamed:));
method_exchangeImplementations(imageMethod, jk_imageMethod);
}
+(UIImage *)jk_imageNamed:(NSString *)imageName
{
   UIImage *image = [UIImage jk_imageNamed:imageName];
   if (image == nil) {
      NSLog(@"图片为空");
    }else
    {
       NSLog(@"图片不为空");
    }
  return image;
}

四.runtime动态添加方法(这里添加的是带参数的方法)



在此定义的是一个Son方法

//
//  Son.m
//  OC的runtime
#import "Son.h"
#import <objc/message.h>
@implementation Son
//定义函数
void eat(id self,SEL _cmd,id patam1)
{
/**
 *  系统默认会传方法
 *
 */
NSLog(@"调用eat %@ %@ %@",self,NSStringFromSelector(_cmd),patam1);
}
//默认一个方法有两个参数,self,_cmd
//self:方法的调用者
//_cmd:调用方法的编号
//动态添加方法,首先实现这个(没有实现的方法会走这里)
+(BOOL) resolveInstanceMethod:(SEL)sel
{
//动态添加eat方法
/**
 *  对象方法的方法添加解释
 *
 *  @param cls#>    给那个类添加方法
 *  @param SEL#>    添加方法的方法编号
 *  @param imp#>    方法实现,函数入口,函数名
 *  @param types#>  方法类型
 *
 */
// class_addMethod(<#__unsafe_unretained Class cls#>, <#SEL name#>, <#IMP imp#>, <#const char *types#>)
    if ([NSStringFromSelector(sel) isEqualToString:@"eat:"])
    {
       // @:对象 : SEL
       class_addMethod(self, sel, (IMP)eat, "v@:@");
        return YES;
     }
     return [super resolveInstanceMethod:sel];
}
@end

五.runtime动态添加属性


给一个类动态的添加属性


我写了一个NSObject+shuxing.h类


NSObject+shuxing.h


生命一个属性

@property(nonatomic,strong) NSString *name;

NSObject+shuxing.m

#import "NSObject+shuxing.h"
#import <objc/message.h>
@implementation NSObject (shuxing)
-(void)setName:(NSString *)name
{
//添加属性与对象有关
//给某个对象产生关联
/**
 *  id object  给哪个对象添加属性
 *  const void *key 属性名,根据key去获取关联的对象  void * == id
 *  id value  关联的值
 *  objc_AssociationPolicy policy  策略,用什么策略去保存
 */
 objc_setAssociatedObject(self, @"name", name, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
-(NSString *)name
{
   return objc_getAssociatedObject(self, @"name");
}
@end


runtime部分代码  密码: kd5y



目录
相关文章
|
Java Android开发 C++
[Android JNI] --- 静态注册和动态注册实现java和native相互调用
[Android JNI] --- 静态注册和动态注册实现java和native相互调用
157 0
|
Java
Java常用API---Runtime(消息机制)含代码例子
私有化构造方法,不能被实例化
182 0
Java常用API---Runtime(消息机制)含代码例子
|
缓存 安全 算法
Framework笔记 | binder详解
Framework笔记 | binder详解
|
开发者
Runtime系列:消息机制【04】
OC中的方法调用的本质,都是转换为objc_msgSend函数的调用。 这里所说的消息机制就是objc_msgSend的执行流程。
164 0
Runtime系列:消息机制【04】
|
Java Spring
Spring源码编译报错:reactor.core.publisher中的MonoProcessor已过时
Spring源码编译报错:reactor.core.publisher中的MonoProcessor已过时
589 0
Spring源码编译报错:reactor.core.publisher中的MonoProcessor已过时
|
iOS开发
iOS - Runtime Swizzling 源码剖析
Runtime源码下载 源码位于objc-class-old.m
|
消息中间件 Java Linux
【Android 异步操作】Handler 机制 ( MessageQueue 消息队列的阻塞机制 | Java 层机制 | native 层阻塞机制 | native 层解除阻塞机制 )(一)
【Android 异步操作】Handler 机制 ( MessageQueue 消息队列的阻塞机制 | Java 层机制 | native 层阻塞机制 | native 层解除阻塞机制 )(一)
595 0
|
消息中间件 Java Android开发
【Android 异步操作】Handler 机制 ( MessageQueue 消息队列的阻塞机制 | Java 层机制 | native 层阻塞机制 | native 层解除阻塞机制 )(二)
【Android 异步操作】Handler 机制 ( MessageQueue 消息队列的阻塞机制 | Java 层机制 | native 层阻塞机制 | native 层解除阻塞机制 )(二)
251 0
|
API Android开发 存储
12.源码阅读(IPC Binder机制-android api 26)
调用bindService方法绑定服务最终会执行Service的onBind方法并在ServiceConnection的onServiceConnected中得到IBinder对象,我们从源码角度看看这一过程是如何进行的 首先从ContextImpl的...
846 0