当前位置: 首页 > news >正文

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

文章目录

    • category
      • 底层结构
      • runtime 执行 category 底层原理
      • 添加成员变量
    • load
      • 调用形式
      • 系统调用形式的内部原理
      • 源码实现逻辑
    • initialize
      • 调用形式
      • 源码核心函数(由上到下依次调用)
      • 如果分类实现了 +initialize

category

底层结构

本质是结构体。
struct _category_t {const char *name;struct _class_t *cls;const struct _method_list_t *instance_methods;const struct _method_list_t *class_methods;const struct _protocol_list_t * protocols;const struct _prop_list_ *properties;
}

其中,cls 指针的结构为:

在这里插入图片描述

runtime 执行 category 底层原理

  • 方法名相同时,category并不会覆盖 class或者 meta-class 中相同名称的方法实现,
    消息机制寻找到第一个方法实现,则不继续向下寻找
  • 在运行时,通过runtime,动态将分类的方法合并到类对象,元类对象中:
    1. for (i = 0; i < used(); i ++)
      根据分类的方法、属性、协议占用内存大小,分别扩充类的:
      方法列表mlists、
      属性列表proplists、
      协议列表protolists
      每一种列表都是二维数组,每一个分类相关数据存储在大数组中的小数组
    2. 通过 memmove(整体移动并覆盖,内部会判断移动方向)移动类对象的方法、属性、协议到最后
    3. 通过 memcoy(单个移动并覆盖)将分类的方法、属性、协议到类中
  • 加载顺序
    类,优先于分类加载,源码采用递归方式,保证类加载的优先级
    分类之间、类与类之间,先编译的先加载,后编译先调用

添加成员变量

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

  • 方案一:
    在+load方法中完成全局字典初始化,对属性进行存取,要维护key的唯一性,且有线程安全问题,内存问题(销毁后仍调用)
  • 方案二:runtime
    #import <objc/runtime.h>
    
    在setter方法中,调用函数:
    objc_setAssociatedObject(self, key , name, objc_ASSOCIATION_ASSIGN)
    
    在getter方法中,调用函数:
    return objc_getAssociatedObject(self, key)
    
    声明key:
    1. 全局 staitic const void *key = &key;
    2. 全局 staitic const char key = &key; // char 减小key内存占用
      • 一定要给key赋初值,保证key的唯一性
      • 这里是把全局变量key的地址值给了key
      • static 保证全局变量只可在文件内访问
      • 不使用static,在外界可使用extern 读写
    3. 直接把key替换为常量字符串(直接声明的字符串放在常量区,内存地址不变)
    4. 直接把key替换为@selector(key). 返回的结构体的指针不变

load

调用形式

  • 一个类的 load方法在启动时都会且仅被调用一次
  • 重写+load,系统调用 ——> 指针访问直接调用
  • [Class load],手动调用 ——> 消息机制

系统调用形式的内部原理

  • 按照编译顺序,谁在前面就先被编译
  • 先调用完所有类的load方法
  • 再调用category的load方法

源码实现逻辑

  1. 通过while循环,判断是否所有类的load方法都被调用
  2. 通过递归处理,先调用父类+load,再调用子类+load
  3. 分类通过for ++ 循环,取出load_method调用
  4. 通过do while循环,完成所有load方法的调用
    在这里插入图片描述

initialize

调用形式

消息机制调用
tips: objc_msgSend() ——> 该函数底层是使用汇编实现的

  • 调用时机
  • 类第一次接收到消息时调用,非启动时调用。
  • 子类的initialize调用之前,先主动调用父类的initialize,再调用子类的initialize。
  • initialize 方法是以懒加载的方式被调用的。

源码核心函数(由上到下依次调用)

  1. 实例方法:class_getInstanceMethod
  2. 静态方法:class_getClassMethod (内部调用class_getInstanceMethod)
  3. if (initialize && !cls->isInitialized) { 递归 _class_initialize(父类) }

如果分类实现了 +initialize

  • 覆盖类本身的+initialize调用
  • 只执行编译顺序最后那个分类的 + initialize

相关文章:

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

文章目录 category底层结构runtime 执行 category 底层原理添加成员变量 load调用形式系统调用形式的内部原理源码实现逻辑 initialize调用形式源码核心函数&#xff08;由上到下依次调用&#xff09;如果分类实现了 initialize category 底层结构 本质是结构体。struct _cat…...

另外知识与网络总结

一、重谈NAT&#xff08;工作在网络层&#xff09; 为什么会有NAT 为了解决ipv4地址太少问题&#xff0c;到了公网的末端就会有运营商路由器来构建私网&#xff0c;在不同私网中私有IP可以重复&#xff0c;这就可以缓解IP地址太少问题&#xff0c;但是这就导致私有IP是重复的…...

怎样用云手机进行TikTok矩阵运营?

在运营TikTok矩阵时&#xff0c;许多用户常常面临操作复杂、设备过多等问题。如果你也感到操作繁琐&#xff0c;不妨考虑使用云手机。云手机具备丰富的功能&#xff0c;能够帮助电商卖家快速打造高效的TikTok矩阵。接下来&#xff0c;我们将详细解析这些功能如何提升你的运营效…...

RTMP播放器全解析

一、RTMP 播放器概述 &#xff08;一&#xff09;RTMP 播放器的定义与作用 RTMP 播放器是一种专门用于播放采用 RTMP&#xff08;Real Time Messaging Protocol&#xff09;协议的视频流的工具。在当今的流媒体播放领域中&#xff0c;它扮演着至关重要的角色。RTMP 播放器能够…...

定期清洗ip是为了什么?怎么清洗iip

定期清洗IP&#xff08;也称为“IP清理”&#xff09;的目的是确保使用的IP池保持高效、可靠、安全&#xff0c;避免因使用无效或被封禁的IP导致网络操作失败。尤其在数据爬取、负载均衡等使用代理的场景中&#xff0c;定期清洗IP有助于提升整体的性能和数据抓取成功率。 定期…...

谁能给我一个ai现在无法替代画师的理由?

小白可做&#xff01;全自动AI影视解说一键成片剪辑工具https://docs.qq.com/doc/DYnl6d0FLdHp0V2ll 如何看待现如今的AI绘画 哎呀玫瑰花来了&#xff0c;所有花式都要玩完了。 我相信大家在网上已经看过了太多惊为天人的AI绘画作品&#xff0c;有人抵制&#xff0c;有人支持&a…...

深入理解MySQL InnoDB中的B+索引机制

目录 一、InnoDB中的B 树索引介绍 二、聚簇索引 &#xff08;一&#xff09;使用记录主键值的大小进行排序 页内记录排序 页之间的排序 目录项页的排序 &#xff08;二&#xff09;叶子节点存储完整的用户记录 数据即索引 自动创建 &#xff08;三&#xff09;聚簇索引…...

语言的输入

编程语言提供最基本的输入输出&#xff0c;输入一个预期的数据也不是看起来那么简单&#xff0c;如下一一展开。 不同输入形式 C语言scanf提供格式串输入&#xff0c;程序员负责配置正确的格式&#xff0c;比如%d整型&#xff0c;%s为字符串。可能出现格式串和变量格式、个数不…...

2024年中国电子学会青少年软件编程(Python)等级考试(二级)核心考点速查卡

考前练习 2024年03月中国电子学会青少年软件编程&#xff08;Python&#xff09;等级考试试卷&#xff08;二级&#xff09;答案 解析 2024年06月中国电子学会青少年软件编程&#xff08;Python&#xff09;等级考试试卷&#xff08;二级&#xff09;答案 解析 知识点描述 …...

OpenCV系列教程二:基本图像增强(数值运算)、滤波器(去噪、边缘检测)

文章目录 一、基本图像增强&#xff08;数值运算&#xff09;1.1 加法 &#xff08;cv2.add&#xff09;1.1.1 图像与标量相加&#xff08;调节亮度&#xff09;1.1.2 图像与图像相加&#xff08;两个图像shape要相同&#xff09;1.1.3 图像的加权加法&#xff08;渐变切换&…...

什么是文件完整性监控(FIM)

组织经常使用基于文件的系统来组织、存储和管理信息。文件完整性监控&#xff08;FIM&#xff09;是一种用于监控和验证文件和系统完整性的技术&#xff0c;识别用户并提醒用户对文件、文件夹和配置进行未经授权或意外的变更是 FIM 的主要目标&#xff0c;有助于保护关键数据和…...

分库分表还是分布式?如何用 OceanBase的单机分布式一体化从根本上解决问题

随着企业业务规模的不断增长&#xff0c;单机集中式的数据库系统逐渐难以承载企业日益增长的数据存储与处理需求。因此&#xff0c;MySQL 的分库分表方案成为了众多企业应对数据存储量激增及数据处理能力需求扩张的“止痛药”。尽管这一方案短期内有效缓解了企业面临的大规模数…...

怎么查看网站是否被谷歌收录,哪些因素影响着网站是否被谷歌收录

一、怎么查看网站是否被谷歌收录 查看网站是否被谷歌收录&#xff0c;有多种方法可供选择&#xff0c;以下是几种常用的方式&#xff1a; 1.使用“site:”指令&#xff1a; 在谷歌搜索引擎的搜索框中输入“site:你的域名网址”&#xff08;注意使用英文冒号&#x…...

【RabbitMQ】面试题

在本篇文章中&#xff0c;主要是介绍RabbitMQ一些常见的面试题。对于前几篇文章的代码&#xff0c;都已经在码云中给出&#xff0c;链接是mq-test: 学习RabbitMQ的一些简单案例 (gitee.com)&#xff0c;如果存在问题的话欢迎各位提出&#xff0c;望共同进步。 MQ的作用以及应用…...

Python软体中使用TensorFlow实现一个简单的神经网络:从零开始

使用TensorFlow实现一个简单的神经网络:从零开始 在现代数据科学和机器学习领域,神经网络是一个强大的工具。TensorFlow是一个广泛使用的开源库,专门用于机器学习和深度学习。本文将详细介绍如何使用TensorFlow实现一个简单的神经网络。我们将从基础概念开始,逐步深入到代…...

StopWath,apache commons lang3 包下的一个任务执行时间监视器的使用

StopWath是 apache commons lang3 包下的一个任务执行时间监视器&#xff0c;与我们平时常用的秒表的行为比较类似&#xff0c;我们先看一下其中的一些重要方法&#xff1a; <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 --> <dependen…...

ELMO理论

目录 1 优点 2 缺点 3.知识点个人笔记 2018年3月份&#xff0c;ELMo出世&#xff0c;该paper是NAACL18 Best Paper。在之前2013年的word2vec及2014年的GloVe的工作中&#xff0c;每个词对应一个vector&#xff0c;对于多义词无能为力。ELMo的工作对于此&#xff0c;提出了一…...

EMU 街机模拟器编译方法

安装ubuntu 16.04 下载gcc 8.2 安装 然后安装automake 1.16 ,1.15 安装jdk8 sdk 里面配套的ndk 21e 编译库 cd ~/emu-ex-plus-alpha/imagine/bundle/all/ export IMAGINE_PATH/home/lxm/emu-ex-plus-alpha/imagine export ANDROID_SDK_ROOT/home/lxm/Sdk export ANDROID_NDK_…...

c++开发之编译curl(windows版本)

在 Windows 上编译支持 OpenSSL 的 cURL 库并不简单&#xff0c;因为涉及到多个库的依赖关系以及工具链的配置。以下是编译支持 OpenSSL 的 cURL 库的详尽步骤&#xff1a; 环境要求 编译工具链&#xff1a; MinGW 或 Visual StudioCMakePerl (用于编译 OpenSSL)NASM (用于编译…...

IT运维挑战与对策:构建高效一体化运维管理体系

在当今数字化时代&#xff0c;IT运维作为企业运营的核心支撑&#xff0c;其重要性不言而喻。然而&#xff0c;随着业务规模的扩大和技术的不断革新&#xff0c;IT运维团队面临着前所未有的挑战。本文旨在深度剖析当前IT运维中存在的主要问题&#xff0c;并探索一体化解决方案&a…...

C++:std::is_convertible

C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...

从WWDC看苹果产品发展的规律

WWDC 是苹果公司一年一度面向全球开发者的盛会&#xff0c;其主题演讲展现了苹果在产品设计、技术路线、用户体验和生态系统构建上的核心理念与演进脉络。我们借助 ChatGPT Deep Research 工具&#xff0c;对过去十年 WWDC 主题演讲内容进行了系统化分析&#xff0c;形成了这份…...

渗透实战PortSwigger靶场-XSS Lab 14:大多数标签和属性被阻止

<script>标签被拦截 我们需要把全部可用的 tag 和 event 进行暴力破解 XSS cheat sheet&#xff1a; https://portswigger.net/web-security/cross-site-scripting/cheat-sheet 通过爆破发现body可以用 再把全部 events 放进去爆破 这些 event 全部可用 <body onres…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序

一、开发环境准备 ​​工具安装​​&#xff1a; 下载安装DevEco Studio 4.0&#xff08;支持HarmonyOS 5&#xff09;配置HarmonyOS SDK 5.0确保Node.js版本≥14 ​​项目初始化​​&#xff1a; ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...

深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南

&#x1f680; C extern 关键字深度解析&#xff1a;跨文件编程的终极指南 &#x1f4c5; 更新时间&#xff1a;2025年6月5日 &#x1f3f7;️ 标签&#xff1a;C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言&#x1f525;一、extern 是什么&#xff1f;&…...

RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程

本文较长&#xff0c;建议点赞收藏&#xff0c;以免遗失。更多AI大模型应用开发学习视频及资料&#xff0c;尽在聚客AI学院。 本文全面剖析RNN核心原理&#xff0c;深入讲解梯度消失/爆炸问题&#xff0c;并通过LSTM/GRU结构实现解决方案&#xff0c;提供时间序列预测和文本生成…...

C++使用 new 来创建动态数组

问题&#xff1a; 不能使用变量定义数组大小 原因&#xff1a; 这是因为数组在内存中是连续存储的&#xff0c;编译器需要在编译阶段就确定数组的大小&#xff0c;以便正确地分配内存空间。如果允许使用变量来定义数组的大小&#xff0c;那么编译器就无法在编译时确定数组的大…...

C/C++ 中附加包含目录、附加库目录与附加依赖项详解

在 C/C 编程的编译和链接过程中&#xff0c;附加包含目录、附加库目录和附加依赖项是三个至关重要的设置&#xff0c;它们相互配合&#xff0c;确保程序能够正确引用外部资源并顺利构建。虽然在学习过程中&#xff0c;这些概念容易让人混淆&#xff0c;但深入理解它们的作用和联…...

嵌入式常见 CPU 架构

架构类型架构厂商芯片厂商典型芯片特点与应用场景PICRISC (8/16 位)MicrochipMicrochipPIC16F877A、PIC18F4550简化指令集&#xff0c;单周期执行&#xff1b;低功耗、CIP 独立外设&#xff1b;用于家电、小电机控制、安防面板等嵌入式场景8051CISC (8 位)Intel&#xff08;原始…...

spring Security对RBAC及其ABAC的支持使用

RBAC (基于角色的访问控制) RBAC (Role-Based Access Control) 是 Spring Security 中最常用的权限模型&#xff0c;它将权限分配给角色&#xff0c;再将角色分配给用户。 RBAC 核心实现 1. 数据库设计 users roles permissions ------- ------…...