iOS分类实现原理

iOS底层原理之Category分类实现原理解析 当我们在Category中重写现有类的方法时,Objective-C的运行时机制会将这个重写的方法添加到方法列表中,并将原始类中的方法替换为新的实现。通过Category,我们可以为现有的类添加新的方法,或者重写现有类的方法。当我们使用Category为一个类添加新的方法时,Objective-C的运行时机制会在方法列表中添加一个新的方法项,来表示这个新增的方法。综上所述,Category是Objective-C中一种强大的特性,它允许我们在不修改原始类的情况下为现有类添加新的方法或者重写现有类的方法。 阅读详情

iOS 分类底层是怎么实现的?
本文将分如下四个模块进行探究

  1. 分类的结构体
  2. 编译时的分类
  3. 分类的加载
  4. 总结

本文使用的runtime源码版本是 objc4 - 680
文中类与分类代码如下

//类
@interface Person : NSObject
@property (nonatomic ,copy) NSString *presonName;
@end

@implementation Person
- (void)doSomeThing{
    NSLog(@"Person");
}
@end
// 分类
@interface Person(categoryPerson)
@property (nonatomic ,copy) NSString *categoryPersonName;
@end

@implementation Person(categoryPerson)
- (void)doSomeThing{
    NSLog(@"categoryPerson");
}
@end

1.分类的结构体

struct _category_t {
    const char *name;//类名
    struct _class_t *cls;//类
    const struct _method_list_t *instance_methods;//category中所有给类添加的实例方法的列表(instanceMethods)
    const struct _method_list_t *class_methods;//category中所有添加的类方法的列表(classMethods)
    const struct _protocol_list_t *protocols;//category实现的所有协议的列表(protocols)
    const struct _prop_list_t *properties;//category中添加的所有属性(instanceProperties)
};

struct category_t {
    const char *name; // 类名
    classref_t cls;   // 分类所属的类
    struct method_list_t *instanceMethods;  // 实例方法列表
    struct method_list_t *classMethods;     // 类方法列表
    struct protocol_list_t *protocols;      // 遵循的协议列表
    struct property_list_t *instanceProperties; // 属性列表

    // 如果是元类,就返回类方法列表;否则返回实例方法列表
    method_list_t *methodsForMeta(bool isMeta) {
        if (isMeta) {
            return classMethods;
        } else {
            return instanceMethods;
        }
    }

    // 如果是元类,就返回 nil,因为元类没有属性;否则返回实例属性列表,但是...实例属性
    property_list_t *propertiesForMeta(bool isMeta) {
        if (isMeta) {
            return nil; // classProperties;
        } else {
            return instanceProperties;
        }
    }
};

2.编译时的分类

2.1分类的属性

// Person(categoryPerson) 属性列表
static struct /*_prop_list_t*/ {
    unsigned int entsize;  // sizeof(struct _prop_t)
    unsigned int count_of_properties;
    struct _prop_t prop_list[1];
} _OBJC_$_PROP_LIST_Person_$_categoryPerson __attribute__ ((used, section ("__DATA,__objc_const"))) = {
    sizeof(_prop_t),
    1,
    {{"categoryPersonName","T@\"NSString\",C,N"}}
};

// Person 属性列表
static struct /*_prop_list_t*/ {
    unsigned int entsize;  // sizeof(struct _prop_t)
    unsigned int count_of_properties;
    struct _prop_t prop_list[1];
} _OBJC_$_PROP_LIST_Person __attribute__ ((used, section ("__DATA,__objc_const"))) = {
    sizeof(_prop_t),
    1,
    {{"presonName","T@\"NSString\",C,N,V_presonName"}}
};

对比上述代码可以发现:在分类中可以声明属性,并且同样会生成一个 _prop_list_t 的结构体

2.2分类的实例变量?

// Person 实例变量列表

static struct /*_ivar_list_t*/ {
    unsigned int entsize;  // sizeof(struct _prop_t)
    unsigned int count;
    struct _ivar_t ivar_list[1];
} _OBJC_$_INSTANCE_VARIABLES_Person __attribute__ ((used, section ("__DATA,__objc_const"))) = {
    sizeof(_ivar_t),
    1,
    {{(unsigned long int *)&OBJC_IVAR_$_Person$_presonName, "_presonName", "@\"NSString\"", 3, 8}}
};

因为 _category_t 这个结构体中并没有 _ivar_list_t
所以在编译时系统没有Person(categoryPerson) 没有生成类似的相应结构体,也没有生成 _categoryPersonName。

2.3分类的实例方法

// Person 实例方法结构体
static struct /*_method_list_t*/ {
    unsigned int entsize;  // sizeof(struct _objc_method)
    unsigned int method_count;
    struct _objc_method method_list[3];
} _OBJC_$_INSTANCE_METHODS_Person __attribute__ ((used, section ("__DATA,__objc_const"))) = {
    sizeof(_objc_method),
    3,
    {{(struct objc_selector *)"doSomeThing", "v16@0:8", (void *)_I_Person_doSomeThing},
    {(struct objc_selector *)"presonName", "@16@0:8", (void *)_I_Person_presonName},
    {(struct objc_selector *)"setPresonName:", "v24@0:8@16", (void *)_I_Person_setPresonName_}}
};

// Person(categoryPerson )实例方法结构体
static struct /*_method_list_t*/ {
    unsigned int entsize;  // sizeof(struct _objc_method)
    unsigned int method_count;
    struct _objc_method method_list[1];
} _OBJC_$_CATEGORY_INSTANCE_METHODS_Person_$_categoryPerson __attribute__ ((used, section ("__DATA,__objc_const"))) = {
    sizeof(_objc_method),
    1,
    {{(struct objc_selector *)"doSomeThing", "v16@0:8", (void *)_I_Person_categoryPerson_doSomeThing}}
};

对比上述方法可以看到:虽然分类可以声明属性,但是编译时,系统并没有生成分类属性的 get/set 方法,所以,这就是为什么分类要利用
runtime 动态添加属性,如何动态添加属性,有兴趣的同学可以查看下面文章 iOS分类中通过runtime添加动态属性

2.4分类的结构体

// Person(categoryPerson ) 结构体
static struct _category_t _OBJC_$_CATEGORY_Person_$_categoryPerson __attribute__ ((used, section ("__DATA,__objc_const"))) = 
{
    "Person",
    0, // &OBJC_CLASS_$_Person,
    (const struct _method_list_t *)&_OBJC_$_CATEGORY_INSTANCE_METHODS_Person_$_categoryPerson,
    0,
    0,
    (const struct _prop_list_t *)&_OBJC_$_PROP_LIST_Person_$_categoryPerson,
};

这是系统在编译时实例化 _category_t 生成的
_OBJC_$_CATEGORY_Person_$_categoryPerson

2.5分类数组

static struct _category_t *L_OBJC_LABEL_CATEGORY_$ [1] __attribute__((used, section ("__DATA, __objc_catlist,regular,no_dead_strip")))= {
    &_OBJC_$_CATEGORY_Person_$_categoryPerson,
};

编译器最后生成了一个数组,数组的元素就是我们创建的各个分类,用来在运行时加载分类。

3.分类的加载

3.1加载分类调用栈

_objc_init
└──map_2_images
    └──map_images_nolock
        └──_read_images

分类加载的调用栈如上述

  • _objc_init 算是整个 objc4 的入口,进行了一些初始化操作,注册了镜像状态改变时的回调函数
  • map_2_images 主要是加锁并调用 map_images_nolock
  • map_images_nolock 在这个函数中,完成所有 class 的注册、fixup等工作,还有初始化自动释放池、初始化 side table 等工作并在函数后端调用了 _read_images
  • _read_images 方法干了很多苦力活,比如加载类、Protocol、Category,加载分类的代码就写在 _read_images 函数的尾部

该调用栈入口函数 void _objc_init(void) 在 objc-os.mm 中,有兴趣的同学可以去看看这些函数里都做了什么

3.2 _read_images 中加载分类的源码

加载分类的源码主要做了两件事

  • 把category的实例方法、协议以及属性添加到类上
  • 把category的类方法和协议添加到类的metaclass上

略去与本文无关的代码,得到如下代码

// 获取 镜像中的所有分类
category_t **catlist = _getObjc2CategoryList(hi, &count);
// 遍历 catlist
for (i = 0; i < count; i++) {
    category_t *cat = catlist[i];
    Class cls = remapClass(cat->cls);
    if (cat->instanceMethods ||  cat->protocols
        ||  cat->instanceProperties) 
    {
        addUnattachedCategoryForClass(cat, cls, hi);
        if (cls->isRealized()) {
            remethodizeClass(cls);
            classExists = YES; 
        }
    }
    if (cat->classMethods  ||  cat->protocols
        /* ||  cat->classProperties */)
    {
        addUnattachedCategoryForClass(cat, cls->ISA(), hi);
        if (cls->ISA()->isRealized()) {
            remethodizeClass(cls->ISA());
        }
    }
}

做上述事情主要用到是如下两个函数

  • addUnattachedCategoryForClass(cat, cls, hi) 为类添加未依附的分类
    执行过程伪代码:
    1.取得存储所有 unattached 分类的列表

    NXMapTable *cats = unattachedCategories();

    2.从 cats 列表中找倒 cls 对应的 unattached 分类的列表

    category_list *list = (category_list *)NXMapGet(cats, cls);

    3.将新来的分类 cat 添加刚刚开辟的位置上

    list->list[list->count++] = (locstamped_category_t){cat, catHeader};

    4.将新的 list 重新插入 cats 中,会覆盖老的 list

    NXMapInsert(cats, cls, list);

    执行完上述过程后,系统将这个分类放到了一个 cls 对应的 unattached 分类的 list 中(有点绕口....),这个 list 会在 remethodizeClass(cls) 方法用到

  • remethodizeClass(cls)
    执行过程伪代码:
    1.取得 cls 类的 unattached 的分类列表

    category_list *cats = unattachedCategoriesForClass(cls, false/*not realizing*/)

    2.将 unattached 的分类列表 attach 到 cls 类上

    attachCategories(cls, cats, true /* 清空方法缓存 flush caches*/);

    执行完上述过程后,系统就把category的实例方法、协议以及属性添加到类上

  • 最后再来看一下
    attachCategories(cls, cats, true /* 清空方法缓存 flush caches*/)内部的实现过程
    1.在堆上创建方法、属性、协议数组,用来存储分类的方法、属性、协议

    method_list_t **mlists = (method_list_t **)malloc(cats->count * sizeof(*mlists));
    property_list_t **proplists = (property_list_t **)malloc(cats->count * sizeof(*proplists));
    protocol_list_t **protolists = (protocol_list_t **)malloc(cats->count * sizeof(*protolists));

    2.遍历 cats ,取出各个分类的方法、属性、协议,并填充到上述代码创建的数组中

    int mcount = 0; // 记录方法的数量
    int propcount = 0; // 记录属性的数量
    int protocount = 0; // 记录协议的数量
    int i = cats->count; // 从后开始,保证先取最新的分类
    bool fromBundle = NO; // 记录是否是从 bundle 中取的
    while (i--) { // 从后往前遍历
      auto& entry = cats->list[i]; // 分类,locstamped_category_t 类型
      // 取出分类中的方法列表;如果是元类,取得的是类方法列表;否则取得的是实例方法列表
      method_list_t *mlist = entry.cat->methodsForMeta(isMeta);
      if (mlist) {
          mlists[mcount++] = mlist; // 将方法列表放入 mlists 方法列表数组中
          fromBundle |= entry.hi->isBundle(); // 分类的头部信息中存储了是否是 bundle,将其记住
      }
      // 取出分类中的属性列表,如果是元类,取得是nil
      property_list_t *proplist = entry.cat->propertiesForMeta(isMeta);
      if (proplist) {
          proplists[propcount++] = proplist; // 将属性列表放入 proplists 属性列表数组中
      }
      // 取出分类中遵循的协议列表
      protocol_list_t *protolist = entry.cat->protocols;
      if (protolist) {
          protolists[protocount++] = protolist; // 将协议列表放入 protolists 协议列表数组中
      }
    }

    3.取出 cls 的 class_rw_t 数据

    auto rw = cls->data();

    4.存储方法、属性、协议数组到 rw

    // 准备 mlists 中的方法
    prepareMethodLists(cls, mlists, mcount/*方法列表的数量*/, NO/*不是基本方法*/, fromBundle/*是否来自bundle*/);
    // 将新属性列表添加到 rw 中的属性列表数组中
    rw->properties.attachLists(proplists, propcount);
    // 释放 proplists
    free(proplists); // 释放 proplists
    // 将新协议列表添加到 rw 中的协议列表数组中
    rw->protocols.attachLists(protolists, protocount);
    // 释放 protolists
    free(protolists); // 释放 protolists
    // 将新协议列表添加到 rw 中的协议列表数组中
    rw->protocols.attachLists(protolists, protocount);
    // 释放 protolists
    free(protolists);

4.总结

至此,本文接近尾声
希望本文的读者能够了解到

  • 分类的结构体
  • 分类中是否能添加属性
  • 分类中是否有实例变量
  • 分类是如何 attach 到类上的

行笔简陋,如有问题,敬请指正



作者:CJS__
链接:http://www.jianshu.com/p/b7169a5a558e
來源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
IC验证 AHB-RAM 项目(二)——接口与事务代码的编写 本文介绍了准备工作及接口、事务相关代码编写要点。在接口部分,重点说明了lvc_ahb_if.sv、rkv_ahbram_if.sv和rkv_ahbram_tb.sv三个关键文件的功能,其中rkv_ahbram_if.sv通过动态任务实现复位信号控制。事务部分则涉及lvc_ahb_types.sv中的枚举类型定义和lvc_ahb_transaction.sv中的随机化变量设置,用于构建AHB传输激励。整个验证环境采用模块化设计,通过接口实现TB与DUT的通信,为后续验证工作奠定基础。 阅读详情

相关推荐

Silvaco TCAD 2018安装后,如何配置TonyPlot 5.0.22.R并解决绘图报错?

本文详细介绍了在Windows系统上安装Silvaco TCAD 2018后,如何正确配置TonyPlot 5.0.22.R并解决常见的绘图报错问题。内容包括版本兼容性分析、环境变量设置、常见错误解决方案以及性能优化建议,帮助用户顺利完成仿真结果的可视化工作。

weixin_31031711的博客 420

iOS分类底层实现原理小记

http://www.jianshu.com/p/b7169a5a558e OS 分类底层是怎么实现的?本文将分如下四个模块进行探究 分类的结构体 编译时的分类 分类的加载 总结 本文使用的runtime源码版本是 objc4 - 680文中类与分类代码如下 //类 @interface Person : NSObject @property (nonato...

diaoju3333的博客 352

windows10 + wsl2安装docker

一、安装wsl https://docs.microsoft.com/zh-cn/windows/wsl/install-win10 1.1以管理员身份运行powershell 1.2执行如下命令 dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart 1.3重启电脑 1.4 重启电脑后,如果需要安装wsl2, 则安装官方文档继续后续操作,因我...

happytree001的博客 1568

多个category实现同一个方法调用的顺序

一​​​​​​准备工作: 搭建环境,新建category项目,添加A,B,C三个分类。 二 测试​​​​与结论: 1.主类和三个分类分别添加+ (void)load方法; 运行项目后,输出结果: 初步可以有以下结论:+load方法的优先级: 父类> 分类,那么分类的优先级是怎么样的呢? 我们调整分类的编译顺序: 结果发现:分类优先级为编译的顺序,从上到下...

小菜媛的博客 5146

QMI8658A和QMC5883L传感器校准全攻略:从零偏校准到椭球拟合

本文详细解析了QMI8658A和QMC5883L传感器的校准方法,从零偏校准到椭球拟合,涵盖了9轴运动传感器的核心误差来源及补偿技术。通过实战案例和数学建模,帮助开发者提升传感器精度,适用于无人机、AR/VR等智能硬件应用。

weixin_29189381的博客 158

Jetson平台XDMA PCIe驱动安装与测试全指南

本文提供了一份在NVIDIA Jetson平台上安装与测试Xilinx FPGA XDMA PCIe驱动的完整指南。详细阐述了驱动作为高速DMA引擎的核心作用,并逐步讲解了从环境准备、驱动编译、内核模块加载到实际数据传输测试的全过程。内容涵盖常见问题排查与性能优化建议,帮助开发者实现Jetson与FPGA间的高速数据通信,适用于自动驾驶、工业视觉等需要异构计算的应用场景。

weixin_29196315的博客 526

iOS原理篇(三) Category/分类/类别

一、Category的实现原理 Class Extension/扩展 简介 二、+load、+initialize、+alloc 、-init 加载过程及作用

zheshawanyier的博客 1369

2025年VSCode AI插件实战:如何用Devika+Continue+Tabby三件套10倍提升开发效率

本文详细介绍了2025年VSCode AI插件Devika、Continue和Tabby的三件套组合,如何通过智能开发工作流10倍提升开发效率。从项目架构生成到上下文感知辅助,再到本地化智能编码,这套方案实现了从需求分析到代码生成的全流程自动化,特别适合中大型项目开发。

weixin_26911099的博客 269

【iOS】分类,扩展与关联对象

上一篇章我们探究了类与对象的底层,这一篇我们探究一下分类,扩展与关联对象由于分类没有成员变量列表,所以无法添加成员变量。与此同时他有属性列表,但只会声明属性,不会去实现set与get方法。如果要在分类中使用属性就需要使用关联对象分类在运行时被整合到类中,扩展在编译时被整合到类中,因此分类中方法不实现不会报警,扩展会扩展常用于声明私有属性与方法如果分类中的方法与类中方法重名,分类中的方法会替代类中的方法。

weixin_72437555的博客 1366

Jupyter Lab 无法启动 Kernel 问题排查与解决总结

使用 curl,telnet,或 Python websocket-client 库可以本地模拟 WebSocket 握手行为,帮助分析服务端响应状态。避免使用 http:// + ws:// 组合方式部署 Jupyter Lab,特别是在远程或跨域访问场景。建议统一采用 https:// + wss:// 方式部署,确保浏览器信任并兼容。确认 WebSocket 已升级为 wss://,内核可正常启动。但在远程访问时,浏览器出于安全策略,默认拒绝 ws:// 协议。

weixin_43866043的博客 1854

[EdgeAI] NXP eIQ 机器学习Toolkit (一):准备篇

eIQ™机器学习(ML)软件开发环境支持在恩智浦EdgeVerse™微控制器和微处理器(包括i.MX RT跨界MCU和i.MX系列应用处理器)上使用ML算法。eIQ ML软件包括称为eIQ Toolkit的ML工作流工具以及推理引擎、神经网络编译器和优化库。............

HowieXue 薛永浩的博客 1万+

iOS高级理论:分类和扩展

在 iOS 开发中,分类(Category)和扩展(Extension)是两种常用的机制,用于对现有类进行扩展和增强。它们可以为现有类添加新的方法、属性或协议,而无需修改原始类的源代码。

长沙火山 3019

LAMMPS-使用MATLAB计算径向分布函数

首先需要使用LAMMPS进行分子动力学模拟,并获取到所需的数据文件,LAMMPS是一款开源的分子动力学模拟软件,可以模拟原子、分子和离子的运动行为,对于本文的目标假设你已经完成了LAMMPS的安装和模拟过程,获得了数据文件。)是一种重要的统计工具,用于描述原子或分子之间的空间分布情况,通过计算RDF可以获得物质的结构信息、相互作用距离以及相位转变等重要参数,本文将介绍如何使用MATLAB计算LAMMPS生成的数据文件的径向分布函数。变量替换为你的实际数据文件的名称。

weixin_50547796的博客 514

iOS OC中分类Category实现原理

//联系人:石虎 QQ:1224614774 昵称:嗡嘛呢叭咪哄   一、概念   1.前言   category是Objective-C 2.0之后添加的语言特性,   category的主要作用是为已经存在的类添加方法。   2.设计思想   Objective-C 中的 Category 就是对装饰模式的一种具体实现。它的主要作用是在不改变原有类的前提下,动态地给这个类添加...

石虎 3392

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

iOS 消息推送原理及实现总结 分类: ios技术 ...

在实现消息推送之前先提及几个于推送相关概念,如下图: 1、 Provider:就是为指定IOS设备应用程序提供Push的服务器,(如果IOS设备的应用程序是客户端的话,那么Provider可以理解为服务端[消息的发起者]); 2、 APNS:Apple Push Notification Service[苹果消息推送服务器]; 3、 iPhone:用来接收APNS下发下来的消...

weixin_33955681的博客 84

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

iOS面试题(七)Objective-C语言 -分类的实现机制、原理(Runtime源码分析)

Objective-C语言 分类(什么是分类?分类的实现机制、原理是怎样的?我们应该怎样为一个分类提供实例变量呢?--涉及到第2点关联对象的考察) 关联对象(Runtime分析和查看分类和关联对象的实现机制、原理) 扩展、代理怎么使用(分类和扩展的区别在哪里?) KVO、KVC( KVO、KVC的实现机制、原理、包括涉及到了哪些设计思想) NSNotification(通知的实现机制...

ochenmengo的博客 1100

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

【iOS开发-背景】关于按钮背景图片的拉伸

关于按钮背景图片拉伸与不拉伸的效果拉伸的效果: 不拉伸的效果 不拉伸的效果 拉伸的效果: 拉伸原理iOS开发中,有一个方法可以将图片按照指定的形式拉伸,拉伸方式为下图,一般拉伸部分都为0: 实现方式 新建一个UIImage的分类 为UIImage扩充一个方法+(UIImage )resizableImage:(NSString )imageName; 然后再按钮所在的ViewCon

沸沸腾的专栏 2722

ios中关于分类认知的一些总结

在IOS中,分类是一个极其便捷的代码管理方式,通过使用分类可以取得以下好处: 1.可以在.m文件中利用分类进行私有方法的添加,达到代码分类明确的作用 2.将代码进行分类,分解体积过于庞大的文件 3.将Framework的私有方法公开化 4.便于团队作业的代码整合   分类的特征是运行时决议,所谓运行时决议便是在代码进行运行时,才将对应的方法、属性、协议等真正添加到宿主类中,使用分类可以...

Horson19的博客 470

iOS OC 底层原理之 category、load、initialize

不能直接添加成员变量,但能通过runtime间接添加。property在category中只生成setter和getter方法声明。

xymspace 1767

【iOS】——分类,扩展以及关联对象

分类中没有成员列表,因此不能添加成员变量。但是有属性列表,可以添加属性的声明,但是不会合成set与get方法,如果要使用分类中的属性,需要使用关联对象。分类在运行的时候被整合到类中,扩展在编译的时候被整合到类中,因此分类中的方法不实现不会报错,扩展就会报错。扩展用于声明私有属性与方法。分类中的方法和类中的方法重名,分类中的方法会代替类中的方法。

qq_72437394的博客 1312

Objective-C 分类底层原理分析

1、什么是分类 iOS分类使用的场景就是把功能模块化,把一组类似的功能扩展出一个分类,便于代码的维护以及功能的分块 2、分类的底层结构 分类在iOS底层的数据结构如下: struct _category_t { const char *name; struct _class_t *cls; const struct _method_list_t *instance_metho...

风起云涌 468

iOS 底层探索篇 ——类的加载原理(下)

iOS 底层探索篇 ——类的加载原理(下)1. 为什么要有ro,rw,rwe2. cls->data()3. extAllocIfNeeded & attachCategories4.分类的懒加载类和分类都实现load类实现load和分类不实现load类不实现load和分类实现load类和分类都不实现load5. 4种不同情况下的分类加载类和分类都实现load 1. 为什么要有ro,rw,rwe ro属于cleanmemory,在编译即确定的内存空间,只读,加载后不会改变内容的空间 rw属

LinShunIos的博客 560

[iOS]类和对象的底层原探索

[iOS]类和对象的底层原探索

m0_74703932的博客 1629

【iOS】—— 分类、扩展和关联对象

一、分类与扩展的区别 1、category类别(分类) 专门用来给类添加新的方法。 不能给类添加成员属性,添加了成员属性,也无法取到。 【注意】:其实可以通过runtime给分类添加属性,即属性关联,重写setter、getter方法。 分类中用@property定义的变量,只会生成变量的setter、getter方法的声明,不能生成方法实现和带下划线的成员变量。 2、extension(类扩展) 可以说成是特殊的分类,也可称作匿名分类。 可以给类添加成员属性,但是是私有变量。 可以给类添加方法,也是

m0_55124878的博客 1047

iOS 底层探索篇 ——类的加载原理(中)

iOS 底层探索篇 ——类的加载原理(中) 上回说到readClass 里面给类加上了名字,那么ro,rw是在哪里加的呢?回到_read_images打上断点一点一点探究。 在remap classes 这里打上断点后运行,发现没有进去。 往下走,看到objc_msgSend_fixup,和类无关就跳过不看。继续往下走discover protocols也和类无关不看。在往下看到protocol references,也和类无关,继续往下走。discover categories,分类,继续跳过。继续往下

LinShunIos的博客 374
上一篇: iOS中保证线程安全的几种方式与性能对比
下一篇: iOS Block原理和内存中位置
直隶码农
博客等级 码龄19年 95粉丝 103原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值