Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Objective-C RunTime概览

Objective-C RunTime概览

作者头像
iOS Development
发布于 2019-02-14 09:42:34
发布于 2019-02-14 09:42:34
70800
代码可运行
举报
运行总次数:0
代码可运行

本文为入门介绍,希望能让第一次接触Runtime概念的朋友有一个概貌了解。

一篇文章,不可能讲完Runtime的全部,但是,分成很多篇讲,又有点「见树木不见森林」的迷糊感觉——自己就是看了很多关于Runtime的文章,看完还是「迷雾重重」(当然,也可能因为资质太过平庸)。

所以,这一篇,尽量涉及。

一句话概括

什么是Runtime?作以下引述。但也不要太奢望看完这些说明后,就会豁然开朗。

官方文档Objective-C Runtime

The Objective-C runtime is a runtime library that provides support for the dynamic properties of the Objective-C language, and as such is linked to by all Objective-C apps. Objective-C的runtime是一个「运行时库」,为OC这门语言提供动态的特性,所有OC应用程序都与之相关联。

The down low on Objective-C Runtime

The Objective-C Runtime is an open source library written in C and Assembler that adds the Object Oriented capabilities to C to create the Objective-C language. Objective-C的Runtime,是一个用C和汇编写的「开源库」,它为C添加了面向对象的特性,从而成就了Objrctive-C这门语言。

The Objective-C languages defers as many decisions as it can from compile time and link time to runtime. Whenever possible, it does things dynamically. This means that the language requires not just a compiler, but also a runtime system to execute the compiled code. The runtime system acts as a kind of operating system for the Objective-C language, it’s what makes the language work. Objective-C可以从『编译时』、『链接时』再到『运行时』,hold住尽可能多的决策。只要有可能,它都是动态地干活儿的。这就意味着,这门语言不仅需要一个编译器,还需要一个runtime系统,用来执行编译的代码。这个runtime系统就好比如是Objective-C的「操作系统」,(runtime系统)让这门语言能工作起来。

简单点理解,Runtime就是一个C和汇编写的代码库——是Objective-C之所以成为Objective-C的一个库。

用一图以助理解:

Runtime概览

另外,可参考: 重识 Objective-C Runtime - Smalltalk 与 C 的融合

Runtime的三个头文件

Runtime这个库是开源的。有兴(能)趣(力)的朋友可以仔细研究。

而平时我们会用到的Runtime函数,基本上在runtime.h, objc.h, message.h这三个头文件中。代码2500行+(主要是runtime.h)

runtime.h

runtime.h中定义了若干「类型(Types)」和「函数(Functions)」。

有我们比较熟悉的MethodIvarCategoryobjc_property_tobjc_class类型,都在这里定义。

另外还有106个函数。如常见的:

object_copy(), class_respondsToSelector(), class_copyMethodList等都在这里面。

objc.h

objc.h中定义了Class, id, SEL, IMP类型。

另外还有6个函数。

message.h

声明了一系列的方法执行函数。

objc_msgSend()objc_msgSendSuper()都定义在这里。

名词解释

isa

isa是一个指针,隐式地存在于实例对象、类中,对象的isa指针指向所属类——因此实例对象能知道自己属于哪个类;类的isa指针指向一个叫「元类(Meta Class))」的玩意儿。

isa指针在三个地方有定义:

  • objc_class结构体有声明,指向类的meta类。(在runtime.h)
  • objc_object结构体有声明,指向对象所属类(在objc.h)
  • NSObject类有有声明,指向对象所属类;(在NSObject.h)

Class

Class定义在objc.h中第37、38行,是一个指向objc_class结构体的指针。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/// An opaque type that represents an Objective-C class.
typedef struct objc_class *Class;

So, Class就是一个「指针变量」。

objc_class结构体在runtime.h第55-70行中有定义:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
struct objc_class {
    Class _Nonnull isa  OBJC_ISA_AVAILABILITY;// isa指针, 指向一个meta类,侧面印证:「类也是对象」

#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 *` */

这个结构体,包括:isa指针、父类指针、类名、成员变量、方法列表、缓存以及协议列表等。

解读一下部分成员:

isa指针 上面介绍isa的时候,说过类也有一个isa指针,我们可以理解为:类本身也是一个对象——「类对象」。是「元类(Meta Class)」的实例(每个类的isa指针指向元类)。

我们熟知的「类方法」,也可以理解为是「类对象」的实例方法。

而这些「元类(Meta Class)」则是「根源类(Root Meta Class)」的实例——所有元类的isa指针最终都指向根元类。根元类的isa指针指向自己,最终完成闭环。

画了一张示意图帮助理解:

isa的指针的指向

struct objc_ivar_list struct objc_ivar_list(ivars),是实例变量列表,保存类所声明的所有实例变量。

objc_method_list struct objc_method_list(methodLists)是方法列表,给某个对象发送消息,就是来这个列表中查找是否有相应方法实现的。

可以动态修改methodLists的值来添加成员方法,这也是Category的实现原理。

struct objc_cache struct objc_cache(cache),用于缓存方法,调用过的方法会缓存到这里,方便以后索引,提高速度。

Method

定义在runtime.h第44行,表示一个方法。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/// An opaque type that represents a method in a class definition.
typedef struct objc_method *Method;

objc_method结构体存储了方法名、方法类型和方法实现。

SEL

定义在objc.h第49、50行中,表示一个方法选择器(可以简单点,理解为方法名,一个C语言的字符串)。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/// An opaque type that represents a method selector.
typedef struct objc_selector *SEL;

IMP

定义在objc.h第54行,表示一个方法的实现。由这个函数指针决定最终执行哪段代码。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/// A pointer to the function of a method implementation. 
#if !OBJC_OLD_DISPATCH_PROTOTYPES
typedef void (*IMP)(void /* id, SEL, ... */ ); 
#else
typedef id _Nullable (*IMP)(id _Nonnull, SEL _Nonnull, ...); 
#endif

MethodSELIMP有什么区别?

  • Method:表示一个方法,本质是一个指向objc_method结构体的指针。
  • SEL(Selector):在运行时用来代表一个方法的名字。
  • IMP(Implementation):表示方法的实现部分。第一个参数id指向调用方法的自身,第二个参数是方法的名字seletor,方法的参数紧随其后。

在消息发送的过程中,这三个概念是可以互相转换的。

可以这样理解:

Runtime中,Class维护了一份分发列表(dispatch table),用于消息分发;列表中每个入口,就是一个方法(Method),这份列表的key是selector(SEL),value是implementation(IMP)。

而后面介绍到的Method Swizzling,就是改变这份列表某两个方法的SEL和IMP的对应关系,让seletor对应一个不同的implementation。

(也有人比喻:SLE是门牌号码,IMP是住户)

id

定义在objc.h第45、46行中,表示一个类的实例对象。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/// A pointer to an instance of a class.
typedef struct objc_object *id;

objc_object这个结构体,定义在objc.h中,这个结构体只有一个指向类的isa指针。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/// Represents an instance of a class.
struct objc_object {
    Class _Nonnull isa  OBJC_ISA_AVAILABILITY;
};

Ivar

定义在runtime.h第44行,表示一个实例变量。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/// An opaque type that represents an instance variable.
typedef struct objc_ivar *Ivar;

Cache

定义在runtime.h第1841行。

typedef struct objc_cache *Cache OBJC2_UNAVAILABLE;

Cache的存在,是为方法调用时的性能优化:实例对象收到消息后,会先从Cache中查找,看是否有方法的实现——Runtime会把调用过的方法缓存到Cache中。

objc_property_t

定义在runtime.h第52,53行。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/// An opaque type that represents an Objective-C declared property.
typedef struct objc_property *objc_property_t;

表示Objective-C中的属性。

Category

runtime.h第49,50行:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/// An opaque type that represents a category.
typedef struct objc_category *Category;

objc_category结构体定义在第1784-1790行。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
struct objc_category {
    char * _Nonnull category_name                            OBJC2_UNAVAILABLE;
    char * _Nonnull class_name                               OBJC2_UNAVAILABLE;
    struct objc_method_list * _Nullable instance_methods     OBJC2_UNAVAILABLE;
    struct objc_method_list * _Nullable class_methods        OBJC2_UNAVAILABLE;
    struct objc_protocol_list * _Nullable protocols          OBJC2_UNAVAILABLE;
}                                                            OBJC2_UNAVAILABLE;

Category可以动态的地为已存在的类添加新的方法。

self & super

先做个实验:

打印:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
NSLog(@"[self class]:%@; [super class]:%@", NSStringFromClass([self class]), NSStringFromClass([super class]));

结果,[self class][super class]的值是一样的。 Why?不应该打印一个子类,一个父类吗?

self,是一个隐藏参数,隐藏在objc_msgSend(id _Nullable self, SEL _Nonnull op, ...)函数中,发送的所有方法,第一个参数都是self。

super不是隐藏参数,是一个「编译器标示符」,它告诉编译器,调用父类的方法,而不是本类的方法。但是,这时候实际上的消息的接收者,还是self。

详解解读:

  • 执行[super class],会先调用objc_msgSendSuper(struct objc_super * _Nonnull super, SEL _Nonnull op, ...)函数;
  • 再根据objc_super结构体的super_class去查找方法实现,,最后调用objc_msgSend(id _Nullable self, SEL _Nonnull op, ...)执行方法的实现。 所以,最后的接收器还是self。

因此,上述打印结果的值是一样的。

消息的传递流程

关于OC中的消息传递流程,画了一张图以帮助理解(流程由下往上):

消息传递流程

Objective-C的消息传递流程,个人划分为三部分

  • 正常的消息传递(Messaging)
  • 消息动态解析(Dynamic Method Resolution)
  • 消息转发(Message Forwarding)又分2小步:
    • Fast forwarding
    • Normal forwarding

第一部分,叫做「正常的消息传递」,那理所当然,后面的就是「不正常」了。事实是:如果能找到方法的实现(IMP/implementation),就不会跳到后面。

Runtime应用

1.获取类的相关情况

比如,我想创建一个类似UITableView的类,然后打算参考一下官方的这个类都声明了哪些方法,可以用以下方式查看(头文件声明的方法并不是全部方法):

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
    /* 获取某个类的方法列表(所有方法) */
    // 这样获取是实例方法(不是类方法)
    Method *methods = class_copyMethodList([UITableView class], &outCount);
    for (NSUInteger methodIndex = 0 ; methodIndex < outCount; methodIndex ++) {
        SEL name = method_getName(methods[methodIndex]);
        NSLog(@"Human-例法方实-%@",NSStringFromSelector(name));
    }

还有很多其他函数:class_getInstanceVariable(), objc_getMetaClass(), class_getClassVariable()等等。

2.动态添加方法的实现

比如,我们用了某个闭源的框架,不幸地,有个bug是:某方法没有实现,导致crash:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
[Animal jump]: unrecognized selector sent to instance

这时候如果等闭源框架的debug更新,比较被动。而利用Runtime,可以动态地添加方法的实现,防止crash:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#import "Bird.h"
#import <objc/runtime.h>

// 创建Animal的子类Bird
@implementation Bird

// 如果没有找到实例方法的实现, 就会回调跳到这里
+ (BOOL)resolveInstanceMethod:(SEL)sel {
    if (sel == @selector(jump)) {
        // 利用Runtime的class_addMethod()函数, 动态添加方法的实现
        class_addMethod(self, sel, (IMP)jumpImp, "v@:");
        return YES;
    }
    return [super resolveInstanceMethod:sel];
}

void jumpImp(id obj, SEL _cmd) {
    NSLog(@"执行了jumpImp(动态添加的方法实现)");
}

@end

3.Method Swizzling

Method Swizzling,可以理解为「交换方法的实现(IMP)」,这是网友的说法,官方并没有这种说法,可见苹果官方应该是不提倡这样做的。

假如有个需求:需要记录App每个页面进入的次数(这个需求和Method Swizzling介绍的一样)

我们可以在viewWillAppear:方法中作一些计数处理。但是,每个页面都要写重复的代码。在这里就可以使用Method Swizzling,「动态地」在官方的基础上增加一些代码,以实现需求。

需要新建一个UIViewController的Category,在load方法中实现互换。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#import "UIViewController+Tracking.h"
#import <objc/runtime.h>

@implementation UIViewController (Tracking)

+ (void)load {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Class class = [self class];
        
        // 拿到两个Method对象
        SEL originalSelector = @selector(viewWillAppear:);
        SEL swizzledSelector = @selector(antony_viewWillAppear:);
        
        Method orignalMethod = class_getInstanceMethod(class, originalSelector);
        Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);

        BOOL didAddMethod = class_addMethod(class, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));
        
        if (didAddMethod == YES) {
            class_replaceMethod(class, swizzledSelector, method_getImplementation(orignalMethod), method_getTypeEncoding(orignalMethod));
        }
        else {
            // 利用method_exchangeImplementations()函数交换两个Method的实现
            method_exchangeImplementations(orignalMethod, swizzledMethod);
        }
    });
}

#pragma mark - Method Swizzling
- (void)antony_viewWillAppear:(BOOL)animated {
    // 因为互换了方法, 这里实际调用的是viewWillAppear:的IMP(不会造成递归)
    [self antony_viewWillAppear:animated];

    // 在这里增加你要的功能
    NSLog(@"这是在viewWillAppear:新增的内容");
}

@end

核心就是用method_exchangeImplementations()函数,互换了viewWillAppear:和antony_viewWillAppear:的实现。

而如果现在创建控制器对象,实际流程是这样的:

  • viewWillAppea:被执行(实际上执行上述Category的antony_viewWillAppear:方法)
  • antony_viewWillAppear:方法内又调用了antony_viewWillAppear:(实际上执行的是系统的viewWillAppear:方法——因为互换了)
  • 最后再执行我们自己添加的代码——这样就实现了需求:所有UIViewController在执行 viewWillAppear:时, 都会调用你增加的代码。从而无须在所有的UIViewController中重复写这部分代码。

Github有个框架:Aspects,就是用Runtime的Method Swizzling实现的,它允许你往任意现存类或实例添加额外的代码。

4.动态添加属性 - 利用Associated Objects(Associative References)

Associative References(关联引用/对象),在runtime.h中定义的三个相关函数:

  • objc_setAssociatedObject()
  • objc_getAssociatedObject()
  • objc_removeAssociatedObjects()

有什么作用呢?

网上有种说法:OC中的Category不能添加属性。

其实严格来说:Category不能添加的是「实例变量」,而属性其实是可以添加的:

  • 不能为Category添加实例变量;否则报错:Instance variables may not be placed in categories
  • 但是可以为Category添加属性,也可以自定义setter、getter,外部也可以访问;但是,这个属性是无意义的,因为不能保存数据(可以返回值,但是不能赋值)。而不能保存数据的原因,是因为没有实例变量「装」数据;

而Associated Objects(关联对象),则可以为Category提供保存数据的地方。

因此Associated Objects(关联对象)就可以:给已有类(封闭的类)添加真正有意义的属性——可以保存数据的属性。

比如,我们要为一个叫做Human的类添加一个属性nickName,就可以:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#import "Human+AdditionalProperties.h"
#import <objc/runtime.h>

@implementation Human (AdditionalProperties)
@dynamic nickName;

// 如果要删除该属性,调用objc_setAssociatedObject()赋值为nil即可,
// 不要用objc_removeAssociatedObjects(), 该函数会删除所有添加的属性
- (void)setNickName:(NSString *)nickName {
    // 参数1: 为哪个对象实现的关联
    // 参数2: 这个关联的key(可以用SEL作为key)
    // 参数3: 需要与对应key(参数2)关联的值(就是外部传入的值)
    // 参数4: 关联的策略(和属性的attribute相对应)
    objc_setAssociatedObject(self, @selector(nickName), nickName, OBJC_ASSOCIATION_COPY_NONATOMIC);
}

- (NSString *)nickName {
    // 参数1: 为哪个对象实现的关联
    // 参数2: 该关联的key
    return objc_getAssociatedObject(self, @selector(nickName));
}
@end

需要再次强调的是:通过Associated Objects为类添加有意义的属性,事实上并不是添加了实例变量,而是通过关联,使属性有保存数据的能力。(可以用class_copyPropertyList()验证,并没有增加实例变量。或者断点看该类的实例,并不会看到有添加了实例变量——虽然能用该属性来存取数据。)

5.归档和解档 一键序列化:

有用过NSKeyedArchiver固化自定义对象到沙盒的朋友应该了解,当一个自定义对象有很多属性,需要一个一个encode(编码)或者decode(解码),是很琐屑的,比如:

自定义类有很多属性

而利用Runtime,则可以简化这个过程——无论类有多少属性:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
- (instancetype)initWithCoder:(NSCoder *)aDecoder {
    self = [super init];
    if (self) {
        unsigned int count = 0;
        // 利用class_copyIvarList()拿到类的所有实例变量
        Ivar *ivars = class_copyIvarList([self class], &count);
        // 再用for循环一次性解档
        for (int i = 0; i < count; i++) {
            Ivar ivar = ivars[i];
            NSString *key = [NSString stringWithUTF8String:ivar_getName(ivar)];
            id value = [aDecoder decodeObjectForKey:key];
            [self setValue:value forKey:key];
        }
    }
    return self;
}

- (void)encodeWithCoder:(NSCoder *)aCoder {
    unsigned int count = 0;
    // 利用class_copyIvarList()拿到类的所有实例变量
    Ivar *ivars = class_copyIvarList([self class], &count);
    // 再用for循环一次性归档
    for (int i = 0; i < count; i++) {
        Ivar ivar = ivars[i];
        NSString *key = [NSString stringWithUTF8String:ivar_getName(ivar)];
        id object = [self valueForKey:key];
        [aCoder encodeObject:object forKey:key];
    }
}

Runtime还有很多应用,有兴趣可以继续找相关资料学习。不过:

Objective-C的Runtime就像一把双刃剑,使用它,风险高,回报也高。它赋予你很大的权力,但只要你犯了哪怕一丁点儿错误,都有可能让程序挂掉。

所以,总原则:能不用,尽量不用。

Conclusion

到这里,估计还是有很多黑人问号:Runtime究竟是什么玩意儿? What the hell is Runtime??

这很正常,学习本来就是一个重复的过程——特别是面对学习曲线还比较陡峭的知识。继续实践、温故知新,相信后面会有更好的了解。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017.11.06 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
Objective-C Runtime 详解
Objective-C的方法调用实则为“发送消息”,我们来看[dog eat]实际会被编译器转化为
零式的天空
2022/03/28
1.3K0
Objective-C Runtime 详解
Objective-C Runtime详解
Objective-C Runtime 最近在学习Runtime的知识,恰巧发现了这篇博客《Objective-C Runtime》,在此基础上,进行了些许补充说明,如有错误或其他想法,欢迎提出交流。 目录 引言 简介 与Runtime交互 RunTime术语 消息 动态方法解析 消息转发 健壮的实例变量 动态添加属性(Object-C Associated Objects) 方法调剂(Method Swizzling) 总结 引言 Objective-C的方法调用实则为“发送消息”,我们来看[dog
BY
2018/05/11
1.8K0
【IOS开发高级系列】Objective-c Runtime专题总结
http://yulingtianxia.com/blog/2014/11/05/objective-c-runtime/
江中散人_Jun
2023/10/16
4080
【IOS开发高级系列】Objective-c Runtime专题总结
[Objective-C Runtime] 类与对象
概述 常说Objective-C是一门动态语言,那么问题来了,这个动态表现在那些方面呢? 其实最主要的表现就是Objective-C将很多静态语言在编译和链接时做的事情放到了运行时去做。 它在运行时实现了对类、方法、成员变量、属性等信息的管理机制,同时,运行时机制为我们开发过程提供很多便利之处,比如: 在运行时创建或者修改一个类; 在运行时修改成员变量、属性等; 在运行时进行消息分发和分发绑定; ...... 与之对应实现的就是Objective-C的Runtime机制。 Runtime基本是C和汇编编写的
Jacklin
2018/05/15
9410
Objective-C的对象模型和runtime机制「建议收藏」
对象(Object): OC中基本构造单元 (building block),用于存储和传递数据。
全栈程序员站长
2022/07/10
3540
Objective-C的对象模型和runtime机制「建议收藏」
iOS开发·runtime原理与实践: 基本知识篇(类,超类,元类,super_class,isa,对象,方法,SEL,IMP)
Tips:苹果公开的源代码在这里可以查,https://opensource.apple.com/tarballs/
陈满iOS
2018/09/10
1.8K1
iOS开发·runtime原理与实践: 基本知识篇(类,超类,元类,super_class,isa,对象,方法,SEL,IMP)
Objective-C Runtime:深入理解类与对象
常说Objective-C是一门动态语言,那么问题来了,这个动态表现在那些方面呢?
Jacklin999
2018/09/12
1.3K0
Objective-C Runtime:深入理解类与对象
iOS 小技能:Method Swizzling (交换方法的IMP)
利用Objective-C Runtimee的动态绑定特性,将一个方法的实现与另一个方法的实现进行交换。交换两个方法的实现一般写在分类的load方法里面,因为load方法会在程序运行前加载一次,而initialize方法会在类或者子类在 第一次使用的时候调用,当有分类的时候会调用多次。
公众号iOS逆向
2022/08/22
1.8K0
iOS 小技能:Method Swizzling (交换方法的IMP)
iOS运行时Runtime基础
本文主要整理了Runtime的相关知识。对于一个iOS开发者来说,掌握Runtime的重要性早已不言而喻。OC能够作为一门优秀的动态特性语言,在其背后默默工作着的就是Runtime。在网上也看过很多资
梧雨北辰
2018/07/11
9420
Objc Runtime 总结
Objc Runtime使得C具有了面向对象能力,在程序运行时创建,检查,修改类、对象和它们的方法。Runtime是C和汇编编写的,这里http://www.opensource.apple.com/source/objc4/可以下到苹果维护的开源代码,GNU也有一个开源的runtime版本,他们都努力的保持一致。苹果官方的Runtime编程指南
用户7451029
2020/06/16
8000
iOS之Runtime原理解读
Runtime简介 做过Android开发的同学都知道,早期的Android系统采用的是Dalvik机制,应用每次运行的时候,字节码都需要通过即时编译器转换为机器码,大大的降低了app的运行效率。在Android 5.0系统之后,系统采用了ART机制,应用在第一次安装的时候,字节码就会预先编译成机器码,以后每次运行速度大大的提高了。 OC是一门动态语言,所以它总是想办法把一些决定工作从编译推迟到运行时,也就是说在iOS的编译系统里,光有编译器是不够的,还需要一个运行时系统 (runtime system)
xiangzhihong
2018/02/06
1.1K0
iOS之Runtime原理解读
iOS开发-Runtime详解
iOS开发-Runtime详解 简介 Runtime 又叫运行时,是一套底层的 C 语言 API,其为 iOS 内部的核心之一,我们平时编写的 OC 代码,底层都是基于它来实现的。比如: [receiver message]; // 底层运行时会被编译器转化为: objc_msgSend(receiver, selector) // 如果其还有参数比如: [receiver message:(id)arg...]; // 底层运行时会被编译器转化为: objc_msgSend(receiver, selec
用户1941540
2018/05/11
7560
关于runtime
Runtime是一套C语言的API,基本是用 C 和汇编写的,封装了很多动态性相关的函数,在这里下到苹果维护的开源代码。主要是使用官方Api,解决我们框架性的需求。
honey缘木鱼
2019/12/26
6120
关于runtime
动态的Objective-C——关于消息机制与运行时的探讨
    Objective-C是一种很优美的语言,至少在我使用其进行编程的过程中,是很享受他那近乎自然语言的函数命名、灵活多样的方法调用方式以及配合IDE流顺畅快编写体验。Objective-C是扩展与C面向对象的编程语言,然而其方法的调用方式又和大多面向对象语言大有不同,其采用的是消息传递、转发的方式进行方法的调用。因此在Objective-C中对象的真正行为往往是在运行时确定而非在编译时确定,所以Objective-C又被称为是一种运行时的动态语言。
珲少
2018/08/15
8440
动态的Objective-C——关于消息机制与运行时的探讨
iOS 开发:『Runtime』详解(一)基础知识
我们都知道,将源代码转换为可执行的程序,通常要经过三个步骤:编译、链接、运行。不同的编译语言,在这三个步骤中所进行的操作又有些不同。
程序员充电站
2019/06/13
1.4K0
图解Objective-C对象模型
MelonTeam
2018/01/04
1.3K0
图解Objective-C对象模型
神经病院Objective-C Runtime入院第一天—isa和Class
我第一次开始重视Objective-C Runtime是从2014年11月1日,@唐巧老师在微博上发的一条微博开始。
一缕殇流化隐半边冰霜
2018/08/30
8160
神经病院Objective-C Runtime入院第一天—isa和Class
Objective-C Runtime 的一些基本使用
在上一篇文章《Objective-C Runtime详解》中我们探讨了Runtime的基本原理,这篇文章我们将总结一下Runtime的一些基本使用 目录 查询方法 给分类添加属性 更换代码的实现方法 动态添加方法 字典转属性 先创建两个类 ClassA.h #import <Foundation/Foundation.h> @interface ClassA : NSObject { // 公有变量 NSString *_publicVar1; NSString *_publ
BY
2018/05/11
1.2K0
NSObject头文件解析 / 消息机制 / Runtime解读 (一)
上面是NSObject对象的头文件类部分, 可以看到还有一个NSObject protocol 我们也仔细看看都有什么协议方法@protocol NSObjec
周希
2019/10/15
1.3K0
神经病院 Objective-C Runtime 出院第三天——如何正确使用 Runtime
到了今天终于要"出院"了,要总结一下住院几天的收获,谈谈Runtime到底能为我们开发带来些什么好处。当然它也是把双刃剑,使用不当的话,也会成为开发路上的一个大坑。
一缕殇流化隐半边冰霜
2018/08/30
1.5K0
神经病院 Objective-C Runtime 出院第三天——如何正确使用 Runtime
相关推荐
Objective-C Runtime 详解
更多 >
领券
💥开发者 MCP广场重磅上线!
精选全网热门MCP server,让你的AI更好用 🚀
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验