简谈runtime运行机制之消息发送与转发

深入解析objc_msgSend:Objective-C消息发送机制与性能优化 动态绑定是Objective-C运行时特性的核心,它允许方法在运行时而非编译期确定实现,从而支持方法交换、动态添加和消息转发等灵活能力。其底层依赖objc_msgSend完成消息发送,通过方法缓存、快慢路径分离和哈希查找等机制,在保证动态性的同时将性能优化至接近静态调用。理解这一机制对于排查unrecognized selector崩溃、优化消息发送性能以及掌握Runtime原理至关重要。在iOS开发中,无论是调试崩溃日志还是分析性能瓶颈,深入objc_msgSend都能提供关键支撑。 阅读详情

首先介绍一下相关的参数信息

一、SEL

SEL又叫选择器,是表示一个方法的selector的指针,其定义如下:

typedef struct objc_selector *SEL;

两个类之间,不管它们是父类与子类的关系,还是之间没有这种关系,只要方法名相同,那么方法的SEL就是一样的。每一个方法都对应着一个SEL。所以在 Objective-C同一个类(及类的继承体系)中,不能存在2个同名的方法,即使参数类型不同也不行。相同的方法只能对应一个SEL。这也就导致 Objective-C在处理相同方法名且参数个数相同但类型不同的方法方面的能力很差;

当然,不同的类可以拥有相同的selector,这个没有问题。不同类的实例对象执行相同的selector时,会在各自的方法列表中去根据selector去寻找自己对应的IMP。

本质上,SEL只是一个指向方法的指针(准确的说,只是一个根据方法名hash化了的KEY值,能唯一代表一个方法),它的存在只是为了加快方法的查询速度。这个查找过程我们将在下面讨论。

我们可以在运行时添加新的selector,也可以在运行时获取已存在的selector,我们可以通过下面三种方法来获取SEL:

1. sel_registerName函数

2. Objective-C编译器提供的@selector()

3. NSSelectorFromString()方法

二、IMP

IMP实际上是一个函数指针,指向方法实现的首地址。其定义如下:

id (*IMP)(id,SEL,...)

第一个参数是指向self的指针(如果是实例方法,则是类实例的内存地址;如果是类方法,则是指向元类的指针),第二个参数是方法选择器(selector),接下来是方法的实际参数param列表。

前面介绍过的SEL就是为了查找方法的最终实现IMP的。由于每个方法对应唯一的SEL,因此我们可以通过SEL方便快速准确地获得它所对应的 IMP,查找过程将在下面讨论。取得IMP后,我们就获得了执行这个方法代码的入口点,此时,我们就可以像调用普通的C语言函数一样来使用这个函数指针 了。

获取到IMP之后,我们可以跳过Runtime的消息传递机制,直接执行IMP指向的函数实现,这样省去了Runtime消息传递过程中所做的一系列查找操作,会比直接向对象发送消息高效一些。

三、Method
用于类定义中的方法,定义如下:
typedef struct objc_method *Method;
 
struct objc_method {
    SEL method_name                 OBJC2_UNAVAILABLE;  // 方法名
    char *method_types                  OBJC2_UNAVAILABLE;
    IMP method_imp                      OBJC2_UNAVAILABLE;  // 方法实现
}
我们可以看到该结构体中包含一个SEL和IMP,实际上相当于在SEL和IMP之间作了一个映射。有了SEL,我们便可以找到对应的IMP,从而调用方法的实现代码
四、objc_method_description
objc_method_description定义了一个Objective-C方法,如下:
struct objc_method_description { SEL name; char *types; };
Runtime提供了一系列的方法来处理与方法相关的操作。下面来简单介绍几个:
(1)方法

// 调用指定方法的实现
id method_invoke ( id receiver, Method m, ... );
 
// 调用返回一个数据结构的方法的实现
void method_invoke_stret ( id receiver, Method m, ... );
 
// 获取方法名
SEL method_getName ( Method m );
 
// 返回方法的实现
IMP method_getImplementation ( Method m );
 
// 获取描述方法参数和返回值类型的字符串
const char * method_getTypeEncoding ( Method m );
 
// 获取方法的返回值类型的字符串
char * method_copyReturnType ( Method m );
 
// 获取方法的指定位置参数的类型字符串
char * method_copyArgumentType ( Method m, unsigned int index );
 
// 通过引用返回方法的返回值类型字符串
void method_getReturnType ( Method m, char *dst, size_t dst_len );
 
// 返回方法的参数的个数
unsigned int method_getNumberOfArguments ( Method m );
 
// 通过引用返回方法指定位置参数的类型字符串
void method_getArgumentType ( Method m, unsigned int index, char *dst, size_t dst_len );
 
// 返回指定方法的方法描述结构体
struct objc_method_description * method_getDescription ( Method m );
 
// 设置方法的实现
IMP method_setImplementation ( Method m, IMP imp );
 
// 交换两个方法的实现
void method_exchangeImplementations ( Method m1, Method m2 );

(2、方法选择器)
// 返回给定选择器指定的方法的名称
const char * sel_getName ( SEL sel );
 
// 在Objective-C Runtime系统中注册一个方法,将方法名映射到一个选择器,并返回这个选择器
SEL sel_registerName ( const char *str );
 
// 在Objective-C Runtime系统中注册一个方法
SEL sel_getUid ( const char *str );
 
// 比较两个选择器
BOOL sel_isEqual ( SEL lhs, SEL rhs );

方法调用流程如下:
在Objective-C中,消息直到运行时才绑定到方法实现上。编译器会将消息表达式[receiver message]转化为一个消息函数的调用,即objc_msgSend。这个函数将消息接收者和方法名作为其基础参数,如以下所示:
objc_msgSend(receiver, selector, arg1, arg2, ...)
该函数的作用有:

1. 首先它找到selector对应的方法实现。因为同一个方法可能在不同的类中有不同的实现,所以我们需要依赖于接收者的类来找到的确切的实现。

2. 它调用方法实现,并将接收者对象及方法的所有参数传给它。

3. 最后,它将实现返回的值作为它自己的返回值。

消息的关键在于我们前面章节讨论过的结构体objc_class,这个结构体有两个字段是我们在分发消息的关注的


1. 指向父类的指针

2. 一个类的方法分发表,即methodLists。

当我们创建一个新对象时,先为其分配内存,并初始化其成员变量。其中isa指针也会被初始化,让对象可以访问类及类的继承体系。

当消息发送给一个对象时,objc_msgSend通过对象的isa指针获取到类的结构体,然后在方法分发表里面查找方法的selector。如果 没有找到selector,则通过objc_msgSend结构体中的指向父类的指针找到其父类,并在父类的分发表里面查找方法的selector。依 此,会一直沿着类的继承体系到达NSObject类。一旦定位到selector,函数会就获取到了实现的入口点,并传入相应的参数来执行方法的具体实 现。如果最后没有定位到selector,则会走消息转发流程,这个我们在后面讨论。

objc_msgSend有两个隐藏参数:

1. 消息接收对象

2. 方法的selector

这两个参数为方法的实现提供了调用者的信息。之所以说是隐藏的,是因为它们在定义方法的源代码中没有声明。它们是在编译期被插入实现代码的。

虽然这些参数没有显示声明,但在代码中仍然可以引用它们。我们可以使用self来引用接收者对象,使用_cmd来引用选择器。如下代码所示:

1
2
3
4
5
6
7
8
9
- strange
{
    id  target = getTheReceiver();
    SEL method = getTheMethod();
 
    if ( target == self || method == _cmd )
        return nil;
    return [target performSelector:method];
}

当然,这两个参数我们用得比较多的是self,_cmd在实际中用得比较少。

获取方法地址

Runtime中方法的动态绑定让我们写代码时更具灵活性,如我们可以把消息转发给我们想要的对象,或者随意交换一个方法的实现等。不过灵活性的提 升也带来了性能上的一些损耗。毕竟我们需要去查找方法的实现,而不像函数调用来得那么直接。当然,方法的缓存一定程度上解决了这一问题。

我们上面提到过,如果想要避开这种动态绑定方式,我们可以获取方法实现的地址,然后像调用函数一样来直接调用它。特别是当我们需要在一个循环内频繁地调用一个特定的方法时,通过这种方式可以提高程序的性能。

NSObject类提供了methodForSelector:方法,让我们可以获取到方法的指针,然后通过这个指针来调用实现代码。我们需要将methodForSelector:返回的指针转换为合适的函数类型,函数参数和返回值都需要匹配上。

我们通过以下代码来看看methodForSelector:的使用:

1
2
3
4
5
6
7
void (*setter)(id, SEL, BOOL);
int i;
 
setter = (void (*)(id, SEL, BOOL))[target
    methodForSelector:@selector(setFilled:)];
for ( i = 0 ; i < 1000 ; i++ )
    setter(targetList[i], @selector(setFilled:), YES);

这里需要注意的就是函数指针的前两个参数必须是id和SEL。

当然这种方式只适合于在类似于for循环这种情况下频繁调用同一方法,以提高性能的情况。另外,methodForSelector:是由Cocoa运行时提供的;它不是Objective-C语言的特性。

消息转发

当一个对象能接收一个消息时,就会走正常的方法调用流程。但如果一个对象无法接收指定消息时,又会发生什么事呢?默认情况下,如果是以 [object message]的方式调用方法,如果object无法响应message消息时,编译器会报错。但如果是以perform…的形式来调用,则需要等到运 行时才能确定object是否能接收message消息。如果不能,则程序崩溃。

通常,当我们不能确定一个对象是否能接收某个消息时,会先调用respondsToSelector:来判断一下。如下代码所示:

if ([self respondsToSelector:@selector(method)]) {
    [self performSelector:@selector(method)];
}

消息转发机制基本上分为三个步骤:

1. 动态方法解析

2. 备用接收者

3. 完整转发

下面我们详细讨论一下这三个步骤。

动态方法解析

对象在接收到未知的消息时,首先会调用所属类的类方法+resolveInstanceMethod:(实例方法)或 者+resolveClassMethod:(类方法)。在这个方法中,我们有机会为该未知消息新增一个”处理方法”“。不过使用该方法的前提是我们已经 实现了该”处理方法”,只需要在运行时通过class_addMethod函数动态添加到类里面就可以了。如下代码所示:

void functionForMethod1(id self, SEL _cmd) {
   NSLog(@"%@, %p", self, _cmd);
}
 
+ (BOOL)resolveInstanceMethod:(SEL)sel {
 
    NSString *selectorString = NSStringFromSelector(sel);
 
    if ([selectorString isEqualToString:@"method1"]) {
        class_addMethod(self.class, @selector(method1), (IMP)functionForMethod1, "@:");
    }
 
    return [super resolveInstanceMethod:sel];
}


备用接收者

如果在上一步无法处理消息,则Runtime会继续调以下方法:

- (id)forwardingTargetForSelector:(SEL)aSelector

如果一个对象实现了这个方法,并返回一个非nil的结果,则这个对象会作为消息的新接收者,且消息会被分发到这个对象。当然这个对象不能是self自身,否则就是出现无限循环。当然,如果我们没有指定相应的对象来处理aSelector,则应该调用父类的实现来返回结果。

使用这个方法通常是在对象内部,可能还有一系列其它对象能处理该消息,我们便可借这些对象来处理消息并返回,这样在对象外部看来,还是由该对象亲自处理了这一消息。如下代码所示


@interface SUTRuntimeMethodHelper : NSObject
 
- (void)method2;
 
@end
 
@implementation SUTRuntimeMethodHelper
 
- (void)method2 {
    NSLog(@"%@, %p", self, _cmd);
}
 
@end
 
#pragma mark -
 
@interface SUTRuntimeMethod () {
    SUTRuntimeMethodHelper *_helper;
}
 
@end
 
@implementation SUTRuntimeMethod
 
+ (instancetype)object {
    return [[self alloc] init];
}
 
- (instancetype)init {
    self = [super init];
    if (self != nil) {
        _helper = [[SUTRuntimeMethodHelper alloc] init];
    }
 
    return self;
}
 
- (void)test {
    [self performSelector:@selector(method2)];
}
 
- (id)forwardingTargetForSelector:(SEL)aSelector {
 
    NSLog(@"forwardingTargetForSelector");
 
    NSString *selectorString = NSStringFromSelector(aSelector);
 
    // 将消息转发给_helper来处理
    if ([selectorString isEqualToString:@"method2"]) {
        return _helper;
    }
 
    return [super forwardingTargetForSelector:aSelector];
}
 
@end

这一步合适于我们只想将消息转发到另一个能处理该消息的对象上。但这一步无法对消息进行处理,如操作消息的参数和返回值。

完整消息转发

如果在上一步还不能处理未知消息,则唯一能做的就是启用完整的消息转发机制了。此时会调用以下方法:


- (void)forwardInvocation:(NSInvocation *)anInvocation

- (void)forwardInvocation:(NSInvocation *)anInvocation

运行时系统会在这一步给消息接收者最后一次机会将消息转发给其它对象。对象会创建一个表示消息的NSInvocation对象,把与尚未处理的消息 有关的全部细节都封装在anInvocation中,包括selector,目标(target)和参数。我们可以在forwardInvocation 方法中选择将消息转发给其它对象。

forwardInvocation:方法的实现有两个任务:

1. 定位可以响应封装在anInvocation中的消息的对象。这个对象不需要能处理所有未知消息。

2. 使用anInvocation作为参数,将消息发送到选中的对象。anInvocation将会保留调用结果,运行时系统会提取这一结果并将其发送到消息的原始发送者。

不过,在这个方法中我们可以实现一些更复杂的功能,我们可以对消息的内容进行修改,比如追回一个参数等,然后再去触发消息。另外,若发现某个消息不应由本类处理,则应调用父类的同名方法,以便继承体系中的每个类都有机会处理此调用请求。

还有一个很重要的问题,我们必须重写以下方法:

1
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector

消息转发机制使用从这个方法中获取的信息来创建NSInvocation对象。因此我们必须重写这个方法,为给定的selector提供一个合适的方法签名。

- (void)forwardInvocation:(NSInvocation *)anInvocation

NSObject的forwardInvocation:方法实现只是简单调用了doesNotRecognizeSelector:方法,它不会转发任何消息。这样,如果不在以上所述的三个步骤中处理未知消息,则会引发一个异常。

从某种意义上来讲,forwardInvocation:就像一个未知消息的分发中心,将这些未知的消息转发给其它对象。或者也可以像一个运输站一样将所有未知消息都发送给同一个接收对象。这取决于具体的实现。

消息转发与多重继承

回过头来看第二和第三步,通过这两个方法我们可以允许一个对象与其它对象建立关系,以处理某些未知消息,而表面上看仍然是该对象在处理消息。通过这 种关系,我们可以模拟“多重继承”的某些特性,让对象可以“继承”其它对象的特性来处理一些事情。不过,这两者间有一个重要的区别:多重继承将不同的功能 集成到一个对象中,它会让对象变得过大,涉及的东西过多;而消息转发将功能分解到独立的小的对象中,并通过某种方式将这些对象连接起来,并做相应的消息转 发。

不过消息转发虽然类似于继承,但NSObject的一些方法还是能区分两者。如respondsToSelector:和isKindOfClass:只能用于继承体系,而不能用于转发链。便如果我们想让这种消息转发看起来像是继承,则可以重写这些方法,如以下代码所示:

- (void)forwardInvocation:(NSInvocation *)anInvocation

- (BOOL)respondsToSelector:(SEL)aSelector   {
       if ( [super respondsToSelector:aSelector] )
                return YES;     
       else {
                 /* Here, test whether the aSelector message can
                  *            
                  * be forwarded to another object and whether that  
                  *            
                  * object can respond to it. Return YES if it can.  
                  */      
       }
       return NO;  
}






- (void)forwardInvocation:(NSInvocation *)anInvocation
Python爬虫实战:利用最新技术爬取微信公众号文章(基于搜狗搜索) 使用最新Python版本确保兼容性和性能:比传统Requests更强大的HTML解析库Playwright:新一代浏览器自动化工具,比Selenium更高效Asyncio:异步IO框架提升爬虫效率Redis:分布式任务队列和去重MongoDB:非关系型数据库存储结构化数据本文详细介绍了如何利用Python最新技术栈构建一个功能强大的微信公众号文章爬虫。通过结合Playwright浏览器自动化、异步IO、分布式任务队列等技术,我们实现了一个能够绕过反爬机制、高效稳定抓取数据的解决方案。 阅读详情

相关推荐

【TM1640】STM32 TM1640芯片驱动程序

以下为.h文件: #ifndef __TM1640_H__ #define __TM1640_H__ #include "stm32f10x.h" #define ADDR_START1640 0XC0 #define DSP1640_DIS 0 #define DSP1640_ENB 1 /* 控制显示 ...

cxw312864660的博客 1万+

iOS中@selector的runtime过程

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_34397291的博客 132

嵌入式AI实战:基于RK3588部署YOLOv11并集成OpenCV实现实时推理(全流程详解)

本文详细介绍了在RK3588芯片上部署YOLOv11目标检测模型的全流程,包括环境搭建、模型转换和实时推理实现。主要内容为:1)通过YOLOv11官方工具将PyTorch模型转为ONNX格式;2)使用RKNN Toolkit2将ONNX模型转换为适配RK3588的RKNN格式;3)在RK3588上结合OpenCV实现实时视频推理功能。教程提供了完整的代码示例和详细步骤说明,帮助开发者快速在边缘设备上部署目标检测模型,实现AI视觉应用的落地。

LXY_LOVE36的博客 213

TensorFlow调试常见问题(pycharm)

1. RuntimeError: Attempted to use a closed Session. 在pycharm下调用tensorflow库时,运行出现以下问题: RuntimeError: Attempted to use a closed Session. 解决方法:将STEP=5000开始的程序整体右移,包含在“with”内 可能遇见的问题:python代码如何整体...

呆呆的猫的博客 3万+

【实践】VECTOR AUTOSAR创建SWC读写CAN信号

在AUTOSAR开发中最必要的功能就是读写CAN信号,本文通过一步步说明,介绍如何开发SWC来读写CAN信号,可以说在AUTOSAR中实现读写CAN信号的实践过程,是一个非常基础且典型的练习。在本篇文章阅读之前,推荐阅读AUTOSAR RTE介绍,本篇文章介绍了RTE的比较全面的介绍了AUTOSAR RTE。理解了RTE之后,才能对SWC的设计更加清楚。话不多说,接着上一篇内容VECTOR DaVinci从0到1搭建工程,此篇文章我们介绍如何在DaVinci Developer中开发SWC访问CAN信号。为

酒无忧的博客 1231

【Transformer】小白入门指南

Transformer是起源于NLP领域,然后在图像、视频、声音等领域都得到了广泛应用的基础架构,是继MLP、CNN、RNN’后的公认的第四大基础模型结构。Transformer技术凭借其卓越的表现和广泛的应用前景,已经成为了机器学习领域的一个关键技术。自从2017年Google提出》一文以来,Transformer架构的出现彻底改变了机器学习和深度学习的格局,尤其是在处理语言模型、生成模型以及多模态学习等领域,Transformer几乎成为了不可或缺的技术基石。

图挖掘领域,新晋砖家 ☞ 未来可期,欢迎和静静一起学习交流吖 2522

数据库课程梳理——SElECT

SELECT语句详细分析 文章目录SELECT语句详细分析单表查询统计函数(聚集函数)WHERE子句ORDER/GROUP BY子句HAVING子句连接查询等值连接自连接外连接多表连接嵌套查询`ANY`与`ALL`的用法EXISTS通过`EXISTS`实现全称量词通过`EXISTS`实现逻辑蕴含集合查询集合操作基于派生表的查询集合查询集合操作基于派生表的查询 单表查询 SELECT * / 列名...

qq_45175218的博客 354

【MicroPython编程-ESP32篇:设备驱动】-BNO08X系列传感器驱动

BNO08X 系列(BNO085/BNO086)是一款系统级封装 (SiP),集成了三轴加速度计、三轴陀螺仪、磁力计以及运行 CEVA SH-2 固件的 32 位 ARM® Cortex™-M0+ 微控制器。SH-2 包含 MotionEngine™ 软件,该软件提供复杂的信号处理算法来处理传感器数据,并提供精确的实时 3D 姿态、航向、校准加速度和校准角速度,以及更高级的上下文输出。BNO08X 集成在一个 28 引脚 LGA 封装中,尺寸为 3.8mm x 5.2mm x 1.1mm。它兼容 Andro

视觉与物联智能 695

iOS runtime——函数/使用方法/使用场景/示例

关于iOS runtime学习之路,主要介绍了大部分runtime函数,并一一做了注释,使用方法,场景等也举了例子,便于理解 转载原址:http://www.jianshu.com/p/58c985408b75# 一.认识一下runtime类 runtime 二.The Runtime 1.Objective-C:是一门简单的语言,95%是C。只是在语

番薯大佬的专栏 2451

【深度学习基础】一篇弄懂训练集、验证集和测试集(呕心沥血版)

在深度学习中,训练集、验证集和测试集是构建和评估模型的核心组成部分。训练集用于模型的学习和参数优化,验证集帮助调整超参数和防止过拟合,而测试集则用于最终评估模型的泛化性能。正确划分和使用这三类数据集,对于开发高效、可靠的深度学习模型至关重要。本文将深入解析它们的作用、划分方法以及在实际应用中的注意事项,帮助你全面理解并掌握数据集的科学使用方法,从而提升模型的实际表现。

十二月的猫 3792

使用 MATLAB/Simulink + Communications Toolbox + 5G Toolbox,构建一个2×2 MIMO-OFDM通信系统

本文通过Simulink+CommunicationsToolbox构建2×2 MIMO-OFDM通信系统,重点实现信道均衡滤波器(ZF与MMSE)的设计与应用。详细介绍了系统架构、建模步骤(包括信道估计、均衡器实现)和仿真场景设计,通过BER、星座图和EVM对比分析验证了MMSE均衡器在抑制噪声和信号恢复方面的优势。文章总结了MIMO均衡的核心原理与实践经验,并提出了扩展至大规模MIMO、深度学习均衡器等优化方向,为无线通信系统设计提供实用指导。

amy_mhd的博客 126

在Myeclipse buildpath 加server lib (server runtime)

使用Myeclipse,将eclipse下的工程复制过来后,发现提示Tomcat 7.0 unbound。缺少Server Runtime。 解决方法如下: 1,File->New->Other->Server->Server(注意在new时,需要勾上Show All Wizards),下一步,选择Apache,Tomcat v7.0 Server,点击finish。 2,项目右键->P

dingqinghu的专栏 1万+

乌鸦搜索算法(CSA)详解:从鸟类智能到优化引擎

乌鸦搜索算法(Crow Search Algorithm,CSA)是2016年由Askarzadeh等人提出的一种新型元启发式优化算法,该算法灵感来源于自然界中乌鸦群体的智能觅食行为。这一创新性算法已成为群体智能优化算法家族中的重要成员,与粒子群优化、遗传算法等传统算法相比,CSA具有原理新颖、参数设置简单、全局搜索能力强等特点。

qq_42212808的博客 1278

iOS-Runtime消息发送、转发机制

在iOS开发中我们经常会遇到这样的crash unrecognized selector sent to instance 0x******

MinggeQingchun的博客 1340

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

iOS Runtime运行机制详解(消息传递、消息转发)

一直想发关于Runtime的文章,但是由于读的资料一多,对Runtime的理解又加深了一些,所以总是改来改去,导致一篇都没发出来(其实是因为懒)。 最近又有小伙伴问我,我也只好再次补老账了。。。 ---------啥是OC Runtime---------- OC Runtime呢,其实就是一个Runtime库。 (那啥是Runtime库呢?给你个小链接:https://www.cnblo...

ws1836300的博客 1720

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

Day2 iOS中的runtime

在runtime中,类被定义为指向objc_class结构体的指针。objc_class结构体中的第一个变量是isa指针,isa指针保存的是指向元类的指针,换句话说,class类的本质就是一个对象,称之为类对象。结构体的数据结构// 指针指向元类#if!__OBJC2__// 指向父类的指针// 类的名字// 类的版本信息,默认为 0long info;// 类的信息,供运行期使用的一些位标识// 该类的实例变量大小;// 该类的实例变量列表// 方法定义的列表// 方法缓存。

weixin_43640566的博客 698

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

ios runtime重要性_iOS Runtime运行机制详解

非常有必要对runtime有一个全面而深入的理解,本文可以帮助读者实现这个愿望,详情请看下文1.讲一下 OC 的消息机制OC中的方法调用其实都是转成了objc_msgSend函数的调用,给receiver(方法调用者)发送了一条消息(selector方法名)objc_msgSend底层有3大阶段消息发送(当前类、父类中查找)、动态方法解析、消息转发2. 什么是Runtime?平时项目中有用过么?O...

weixin_34675606的博客 201

IOS runtime运行机制详解(一)

OC运行机制是指,可以运行的时候动态调用函数。因为C语言必须在编译的时候就决定调用哪个函数。 我们平时写的OC代码,它在运行的时候也是转换成了runtime的方式运行的。任何方法调用本质:就是发送一个消息。(用runtime发送消息,OC底层通过runtime实现)每一个OC的方法,底层必然有一个与之对应的runtime运行方法。也就是说任何方法调用,都是转换为消息机制。 面试题:说说IOS ...

weixin_30248399的博客 303

runtime运行机制

runtime是实现机制是什么?一般用于干什么?下面笔者就分享给大家了,有什么不足之处,希望大家指点建议。 runtime 是一套比较底层的纯C语言的API,属于一个C语言库,包含了很多底层C语言的API。 在我们平常写的oc代码中,程序运行的过程中,最终转变成runtime的C语言代码,runtime是OC的幕后工作者, 比如说:下面一个创建对象的方法中 OC: per

Jet Huang 的专栏 1141

教你深刻理解Runtime机制

教你深刻理解Runtime机制 什么是Runtime? 概念 Objective-C是基于C语言加入面向对象特性和消息转发机制的动态语言,这就是说它不仅需要一个编译器,还需要Runtime系统动态的创建类和对象,进行消息发送和转发。关于Runtime概念众说纷纭。理解Runtime,我们从源码开始…. 源码介绍 Runtime在实际开发中,其实就是一组C语言函数。 官方介绍:官方文...

hou_manager的博客 1777

OC的runtime运行机制

OC的runtime运行机制oc是一个全动态语言,oc的一切都是基于runtime实现的! runtime应用的时机: 当需要非常高的性能开发时,使用runtime(oc的代码已经无法满足性能需求) 当我们对系统内部的实现很好奇的时候,可以用clang反编译成c++去看底层的实现机制! runtime实现的机制是什么,怎么用,一般用于干嘛? runtime是一套比较底层的纯C语言API, 属于

qq_31502071的博客 668

iOS runtime运行机制

RunTime简称运行时,就是系统在运行的时候的一些机制。对于C语言而说,函数的调用在编译的时候会决定调用哪个函数,编译完成之后直接顺序执行,但是对于OC来说,函数的调用指的是消息发送,在编译的时候并不能决定真正调用哪个函数,只有在真正运行的时候才会根据函数的名称找到对应的函数进行调用。

烂笔头 617

iOS中runtime运行机制解析

iOS中runtime运行机制解析 http://blog.youkuaiyun.com/fuzheng0301/article/details/46898405

LiuShuaile的博客 595

java runtime 运行机制_深入理解 runtime(运行时)机制—— 整理

runtime 就是系统在运行时的一些机制,其中最主要的是消息机制。OC代码,最终都是转成了runtime(c语言库)的C语言实现。eg:类转成了runtime库里面的结构体等数据类型方法转成了runtime库里面的C语言函数,平时调方法都是转成了objc_msgSend函数(所以说OC有个消息发送机制)[Entityalloc]init]objc_msgSend("Entity","all...

weixin_42396174的博客 764

oc - runtime运行机制

  Objective-C语言是一门动态语言,它将很多静态语言在编译和链接时做的事放到了运行时来处理。同时OC也是一门简单的语言,很大一部分是C的内容,只是在语言层面上加了关键字和语法,真正让OC强大的是它的运行时,它很小却很强大,其中核心是消息分发。这种动态语言的优势在于:我们写代码时更加灵活,如我们可以把消息转发给我们想要的对象,或者随意交换一个方法的实现。 这...

weixin_33948416的博客 122

【iOS】Runtime源码(上)

OC是一门动态语言,很多工作需要推到代码真正运行的时候才能做,这时候仅仅在编译时就确定代码就显得有些不够用了,于是还需要有一个运行时系统来执行编译后的代码,这就是OC的Runtime,是整个OC动态特性的基石Runtime基本上是用C和汇编写的,上面介绍的的实现就是通过汇编,可见苹果为了维持这套动态系统的高效性的努力,这是源码中的相关定义,具体实现在.s的汇编文件中这里有一份编译好的 Runtime 源码,可以下载下来自己瞅瞅。

2505_93363502的博客 303
上一篇: 简单瀑布流实现
下一篇: iOS 获取当前设备连接Wi-Fi的方法总结
敬业的程序猿
博客等级 码龄11年 51粉丝 77原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值