热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

iOS经典面试题之深入解析Runtime如何通过selector找到对应的IMP地址

篇首语:本文由编程笔记#小编为大家整理,主要介绍了iOS经典面试题之深入解析Runtime如何通过selector找到对应的IMP地址相关的知识,希望对你有一定的参考价值。

篇首语:本文由编程笔记#小编为大家整理,主要介绍了iOS经典面试题之深入解析Runtime如何通过selector找到对应的IMP地址相关的知识,希望对你有一定的参考价值。



  • 类对象中有类方法和实例方法的列表,列表中记录着方法的名词、参数和实现,而 selector 本质就是方法名称,runtime 通过这个方法名称就可以在列表中找到该方法对应的实现。
  • 如下所示,objc_class 的底层定义声明了一个指向 struct objc_method_list 指针的指针,可以包含类方法列表和实例方法列表:

struct objc_class
Class _Nonnull isa OBJC_ISA_AVAILABILITY;
#if !__OBJC2__
Class _Nullable super_class OBJC2_UNAVAILABLE;
const char * _Nonnull name OBJC2_UNAVAILABLE;
long version OBJC2_UNAVAILABLE;
long info OBJC2_UNAVAILABLE;
long instance_size OBJC2_UNAVAILABLE;
struct objc_ivar_list * _Nullable ivars OBJC2_UNAVAILABLE;
struct objc_method_list * _Nullable * _Nullable methodLists OBJC2_UNAVAILABLE;
struct objc_cache * _Nonnull cache OBJC2_UNAVAILABLE;
struct objc_protocol_list * _Nullable protocols OBJC2_UNAVAILABLE;
#endif
OBJC2_UNAVAILABLE;
/* Use `Class` instead of `struct objc_class *` */

  • 在寻找 IMP 的地址时,runtime 提供两种方法:

IMP class_getMethodImplementation(Class cls, SEL name);
IMP method_getImplementation(Method m);

  • 对于 class_getMethodImplementation 方法而言,类方法和实例方法实际上都是通过调用 class_getMethodImplementation() 来寻找 IMP 地址:

- (void)getIMP_class_getMethodImplementationFromSelector:(SEL)aSelector
const char *className = object_getClassName([self class]);
// 获取实例的 IMP
IMP instanceIMP = class_getMethodImplementation(objc_getClass(className), aSelector);
// 获取类的 IMP
IMP classIMP = class_getMethodImplementation(objc_getMetaClass(className), aSelector);
NSLog(@"instanceIMP:%p classIMP:%p", instanceIMP, classIMP);


  • 对 method_getImplementation 而言,传入的参数只有 method:

- (void)getIMP_method_getImplementationFromSelector:(SEL)aSelector
const char *className = object_getClassName([self class]);
// 获取类中的某个实例方法
Method instanceMethod = class_getInstanceMethod(objc_getClass(className), aSelector);
// 获取类中的某个类方法
Method classMethod = class_getClassMethod(objc_getClass(className), aSelector);
// 获取实例的 IMP
IMP instanceIMP = method_getImplementation(instanceMethod);
// 获取类的 IMP
IMP classIMP = method_getImplementation(classMethod);
NSLog(@"instanceIMP:%p classIMP:%p", instanceIMP, classIMP);


  • 区分类方法和实例方法在于封装 method 的函数:

// 类方法
Method class_getClassMethod(Class cls, SEL name)
// 实例方法
Method class_getInstanceMethod(Class cls, SEL name)

  • 最后调用 IMP method_getImplementation(Method m) 获取 IMP 地址。
  • 方法列表中保存着下面方法的结构体,结构体中包含这方法的实现,selector 本质就是方法的名称,通过该方法名称,即可在结构体中找到相应的实现:

struct objc_method
SEL method_name
char *method_types
IMP method_imp


推荐阅读
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • eclipse学习(第三章:ssh中的Hibernate)——11.Hibernate的缓存(2级缓存,get和load)
    本文介绍了eclipse学习中的第三章内容,主要讲解了ssh中的Hibernate的缓存,包括2级缓存和get方法、load方法的区别。文章还涉及了项目实践和相关知识点的讲解。 ... [详细]
  • Java中包装类的设计原因以及操作方法
    本文主要介绍了Java中设计包装类的原因以及操作方法。在Java中,除了对象类型,还有八大基本类型,为了将基本类型转换成对象,Java引入了包装类。文章通过介绍包装类的定义和实现,解答了为什么需要包装类的问题,并提供了简单易用的操作方法。通过本文的学习,读者可以更好地理解和应用Java中的包装类。 ... [详细]
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 本文介绍了为什么要使用多进程处理TCP服务端,多进程的好处包括可靠性高和处理大量数据时速度快。然而,多进程不能共享进程空间,因此有一些变量不能共享。文章还提供了使用多进程实现TCP服务端的代码,并对代码进行了详细注释。 ... [详细]
  • 开发笔记:select from具体执行相关知识介绍及案例分析
    本文由编程笔记小编整理,主要介绍了select from具体执行相关的知识,包括数据插入、查询最小rowID、查询每个重复名字的最小rowID、删除重复数据等操作,并提供了案例分析。希望对读者有一定的参考价值。 ... [详细]
  • 本文详细介绍了Spring的JdbcTemplate的使用方法,包括执行存储过程、存储函数的call()方法,执行任何SQL语句的execute()方法,单个更新和批量更新的update()和batchUpdate()方法,以及单查和列表查询的query()和queryForXXX()方法。提供了经过测试的API供使用。 ... [详细]
  • 本文介绍了在Vue项目中如何结合Element UI解决连续上传多张图片及图片编辑的问题。作者强调了在编码前要明确需求和所需要的结果,并详细描述了自己的代码实现过程。 ... [详细]
  • 本文介绍了Android 7的学习笔记总结,包括最新的移动架构视频、大厂安卓面试真题和项目实战源码讲义。同时还分享了开源的完整内容,并提醒读者在使用FileProvider适配时要注意不同模块的AndroidManfiest.xml中配置的xml文件名必须不同,否则会出现问题。 ... [详细]
  • 本文讨论了clone的fork与pthread_create创建线程的不同之处。进程是一个指令执行流及其执行环境,其执行环境是一个系统资源的集合。在调用系统调用fork创建一个进程时,子进程只是完全复制父进程的资源,这样得到的子进程独立于父进程,具有良好的并发性。但是二者之间的通讯需要通过专门的通讯机制,另外通过fork创建子进程系统开销很大。因此,在某些情况下,使用clone或pthread_create创建线程可能更加高效。 ... [详细]
  • MyBatis多表查询与动态SQL使用
    本文介绍了MyBatis多表查询与动态SQL的使用方法,包括一对一查询和一对多查询。同时还介绍了动态SQL的使用,包括if标签、trim标签、where标签、set标签和foreach标签的用法。文章还提供了相关的配置信息和示例代码。 ... [详细]
  • 本文详细介绍了如何使用MySQL来显示SQL语句的执行时间,并通过MySQL Query Profiler获取CPU和内存使用量以及系统锁和表锁的时间。同时介绍了效能分析的三种方法:瓶颈分析、工作负载分析和基于比率的分析。 ... [详细]
  • JDK源码学习之HashTable(附带面试题)的学习笔记
    本文介绍了JDK源码学习之HashTable(附带面试题)的学习笔记,包括HashTable的定义、数据类型、与HashMap的关系和区别。文章提供了干货,并附带了其他相关主题的学习笔记。 ... [详细]
  • 本文介绍了在iOS开发中使用UITextField实现字符限制的方法,包括利用代理方法和使用BNTextField-Limit库的实现策略。通过这些方法,开发者可以方便地限制UITextField的字符个数和输入规则。 ... [详细]
author-avatar
弹指遮天的小指头
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有