美文网首页iOS开发实用技术iOS面试总结
runtime消息发送机制-动态添加方法

runtime消息发送机制-动态添加方法

作者: yahibo | 来源:发表于2019-05-18 19:30 被阅读42次

一、消息发送机制

主要使用objc_msgSend()函数:

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

第一个参数self:某一个对象或者某个类(类也是一个对象一个指针);
第二个参数sel:函数指针指向第一个参数(对象或类)对应的函数;
第三个及往后的参数:第二个参数(函数)对应的参数值。

主要使用函数:

1、通过字符串获取一个Class类
objc_getClass("People");
等价于:Class NSClassFromString(@"People");
2、通过方法的字符串形式获取类方法或实列方法SEL
sel_registerName("alloc");
等价于:SEL NSSelectorFromString(@"alloc");
等价于:SEL @selector(alloc);

1、使用消息发送机制创建对象调用方法:

People *p = objc_msgSend(objc_getClass("People"), sel_registerName("alloc"));
p = objc_msgSend(p, sel_registerName("init"));
objc_msgSend(p, sel_registerName("eat"));
//发送参数
objc_msgSend(p, sel_registerName("eat:what:"),@"吃",@"鱼");

2、进入项目文件中使用clang(c、c++、oc的轻量级编译器)重写main.m文件会生成main.cpp文件,即OC对应的c语言代码

//终端进入文件中执行clang命令:
clang -rewrite-objc main.m

OC代码:

#import <Foundation/Foundation.h>
#import "People.h"
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        People *p = [[People alloc] init];
        [p performSelector:@selector(eat)];
    }
    return 0;
}

C代码:

int main(int argc, const char * argv[]) {
    /* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool; 
        People *p = ((People *(*)(id, SEL))(void *)objc_msgSend)((id)((People *(*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("People"), sel_registerName("alloc")), sel_registerName("init"));
        ((id (*)(id, SEL, SEL))(void *)objc_msgSend)((id)p, sel_registerName("performSelector:"), sel_registerName("eat"));
    }
    return 0;
}

观察以上代码可知,对象创建方法调用,均通过消息发送机制完成。同时可以看出OC代码最终编译成C语言对应的结构体、函数等类型。

二、动态添加方法

主要使用class_addMethod()函数:

class_addMethod(Class  _Nullable __unsafe_unretained cls, SEL  _Nonnull name, IMP  _Nonnull imp, const char * _Nullable types)

第一个参数cls:当前对象的类;
第二个参数SEL name:指当前调用的实列方法;
第三个参数imp:函数名称或函数指针指向当前类中添加的函数;
第四个参数types:对应的参数可写""或"v@:@"。

主要使用函数:

1、通过字符串获取一个Class类
objc_getClass("People");
等价于:Class NSClassFromString(@"People");
2、通过方法的字符串形式获取类方法或实列方法SEL
sel_registerName("alloc");
等价于:SEL NSSelectorFromString(@"alloc");
等价于:SEL @selector(alloc);

通过消息发送机制发送消息,调用的函数不存在系统会crash报错
并且会调用resolveInstanceMethod方法:

+(BOOL)resolveInstanceMethod:(SEL)sel;

因此可以在该方法内部添加对应的方法作为提示

//没有找到方法会调用该方法
+(BOOL)resolveInstanceMethod:(SEL)sel{
    //强制转换去除警告
    class_addMethod(self.class, sel, (IMP)noMethod, "");
    return [super resolveInstanceMethod:sel];
}
//动态添加的方法
void noMethod(){
    NSLog(@"没找到这个方法");
}
/*
完整写法
 1、方法调用者
 2、方法编号
 3、方法的第一个参数
 self _cmd隐式参数 每个方法都有两个隐式参数
 对应:objc_msgSend(p, @selector(sleep),@"yahibo");
 */
void noMethod(id self,SEL _cmd,NSString *obj){
    NSLog(@"没找到这个方法arg->%@",obj);
}

OC中的每一个方法均对应有两个隐式参数 id self和SEL _cmd第三个参数则函数对应的参数

相关文章

  • runtime 消息机制简析

    runtime 消息机制消息机制可以简单分为三个方面:消息发送、动态方法解析、消息转发一.消息发送oc 中所有的方...

  • runtime的实用性讲解

    runtime 概念 runtime 运行时机制,主要是消息机制。OC 中的方法调用属于消息的发送,动态调用过程,...

  • runtime消息发送机制-动态添加方法

    一、消息发送机制 主要使用objc_msgSend()函数: 第一个参数self:某一个对象或者某个类(类也是一个...

  • Runtime-原理

    runtime初探对象与方法的本质runtime-消息发送runtime-动态方法解析runtime-消息转发 r...

  • iOS - Runtime - 概念和方法交换

    runtime的概述runtime的相关概念runtime消息机制消息传递动态方法解析消息转发runtime的作用...

  • 方法调用底层实现

    runtime怎么实现方法的调用 :消息机制,runtime系统会把方法调用转化为消息发送。即objc-msgSe...

  • oc动态运行时特征(Runtime)

    oc是门动态语言,是运行时机制。 1、发送消息 Runtime最核心的功能就是它的消息机制,方法的调用其实就是让对...

  • 08.Objective-C 消息机制

    问题 消息机制的三个阶段 1.消息机制发送消息阶段-消息发送2.消息机制动态方法解析阶段 -动态解析3.消息机制消...

  • MG--iOS 消息机制

    msgSend 消息发送 动态方法解析 动态添加方法image.png 消息转发

  • Runtime - 方法发送机制土味讲解

    Runtime - 方法发送机制土味讲解 Runtime - 方法发送机制土味讲解

网友评论

    本文标题:runtime消息发送机制-动态添加方法

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