美文网首页我爱编程
简析OC的消息转发机制

简析OC的消息转发机制

作者: melody5 | 来源:发表于2018-05-28 11:53 被阅读17次

什么是消息转发?其实OC的方法调用就是消息转发的过程,比如创建一个名为Persion的类,调用alloc和init方法,其实就是给系统发送了“alloc”和“init”消息,代码如下:

    // alloc :分配内存空间 malloc()用来分配内存的,告诉系统,给我一块空间                 
    // init  :初始化对象,属性&方法
    Persion *p = [[Persion alloc] init];

接下来我们就具体看一下他是怎么发送消息的
首先我们的导入头文件#import <objc/message.h>,因为从ios5以后苹果是不推荐使用这个底层函数的,所以得设置一下,就是在Build Settings里搜索msg,把这个参数改为NO,如图:


image.png

平时我们调OC的方法是这样,比如先在perison类里实现一个方法,然后在外边调用一下

#import "Persion.h"

@implementation Persion
-(void)sleep {
    NSLog(@"睡了!!!");
}
@end
    Persion *p = [[Persion alloc] init];
    [p sleep];
2018-05-25 14:59:13.229804+0800 消息转发机制[11297:262465] 吃!!!

然后我们点进<objc/message.h>的头文件,可以看到有这样一个方法

objc_msgSend(id _Nullable self, SEL _Nonnull op, ...)

没错这个就是用来发送消息的方法,从提示可以大致看出需要传什么参数了,接下来就用它替换一下上边的代码,像这样:

    Persion *p = objc_msgSend([Persion class], @selector(alloc));
    p = objc_msgSend(p, @selector(init));
    [p sleep];
2018-05-25 15:51:23.654009+0800 消息转发机制[11939:332368] 睡了!!!

试试开始明白点什么了,嘿嘿!
上边的代码中还是有一些OC的代码,我们还能用C语言的函数来替换一下:

    Persion *p = objc_msgSend(objc_getClass("Persion"), sel_registerName("alloc")); 
    p = objc_msgSend(p, sel_registerName("init"));
    [p sleep];
2018-05-25 15:55:47.188866+0800 消息转发机制[12018:338981] 睡了!!!

其实在.m文件编译后,我们的alloc和init方法就被编译成了上边的C语言代码。
还有就是我们看objc_msgSend(id _Nullable self, SEL _Nonnull op, ...),参数最后又三个点,说明它是可扩展,那我们就试着传个参数试试,首先把Persion的方法改下:

-(void)sleepWithTime:(NSString *)time {
    NSLog(@"睡了%@!!!",time);
}
    Persion *p = objc_msgSend(objc_getClass("Persion"), sel_registerName("alloc"));
    p = objc_msgSend(p, sel_registerName("init"));
    objc_msgSend(p, sel_registerName("sleepWithTime:"), @"3小时");
2018-05-25 16:17:55.577908+0800 消息转发机制[12294:365274] 睡了3小时!!!

完美!!!

到这里在给大家介绍一个方法,objc_msgSendSuper(<#struct objc_super * _Nonnull super#>, <#SEL _Nonnull op, ...#>),从方法名可以看出,它就是给父类发消息的方法了,首先创建一个Persion的子类,oldPersion,然后实现父类的方法

-(void)sleepWithTime:(NSString *)time {
    NSLog(@"子类的方法");
}

objc_msgSendSuper从提示可以看出第一个参数是个父类的结构体,点进去看


image.png

两个参数:

  1. receiver:一个实例,也就是我们oldPersion的实例
  2. super_class父类的类型
    于是我们先创建一个结构体,然后把它的地址作为objc_msgSendSuper的第一个参数。

然后第二步就是给父类发消息了,像这样

    oldPersion *p = [[oldPersion alloc] init];
    
    struct objc_super oldSuper = {p ,class_getSuperclass(objc_getClass("oldPersion"))};
    objc_msgSendSuper(&oldSuper, sel_registerName("sleepWithTime:"), @"8小时");
2018-06-28 10:46:58.155 消息转发机制[232:7780] 睡了8小时!!!

最后oldPersion跳过自己的方法,调用了父类的方法。

相关文章

  • 简析OC的消息转发机制

    什么是消息转发?其实OC的方法调用就是消息转发的过程,比如创建一个名为Persion的类,调用alloc和init...

  • 关于Runtime 消息发送机制的延伸

    说到OC 不得不说一下OC 的消息转发机制;何为OC 的消息转发机制;其实就是这样的; Objc 在向一个对象发送...

  • OC消息机制,消息转发机制

    Runtime简称运行时,其中最主要的是消息机制 概述 C 与 OC 的不同 1.C 语言,函数的调用在编译的时候...

  • Runtime知识点整理1

    OC消息机制?消息转发机制流程?什么是Runtime?什么场景下使用? ==============巴拉巴拉......

  • oc消息转发机制

    一、消息转发机制 在OC中,调用一个对象的方法,实际上是给对象发了一条消息,在编译Objective-C函数调用的...

  • OC消息转发机制

    当一个对象收到它没实现的消息的时候,通常会发生如下的情况。 调用+(BOOL)resolveInstanceMet...

  • OC 消息转发机制

    首先了解几个概念:class 的定义 method的定义 消息转发本质:在运行时将方法地址(imp)和一个名字(s...

  • OC 消息转发机制。

    当调用一个 NSObject 对象不存在的方法时,并不会马上抛出异常,而是会经过多层转发,层层调用对象的-reso...

  • OC 消息转发机制

    首先我们看一下objc_msgSend它具体是如何发送消息: 首先根据receiver对象的isa指针获取它对应的...

  • OC消息转发机制

    消息转发的两大阶段 先征询接收者,所属的类,看其是否能够动态添加方法,以处理这个『未知的选择子』,这叫做动态方法解...

网友评论

    本文标题:简析OC的消息转发机制

    本文链接:https://www.haomeiwen.com/subject/xogsjftx.html