【iOS】分类、扩展、关联对象
分类、扩展、关联对象
- 前言
- 分类
- 扩展
- 扩展和分类的区别
- 关联对象
- key的几种用法
- 流程
- 总结
前言
最近的学习中笔者发现自己对于分类、扩展相关知识并不是很熟悉,刚好看源码类的加载过程中发现有类扩展与关联对象详解。本篇我们来探索一下这部分相关知识,首先我们要记住扩展是编译时就被添加在类中,而分类是在运行时才被整合到类信息中来的。
分类
这里我们先来看看使用Clang
编译之后,分类的底层结构struct category_t
:
这里我们来看看其中的内容,根据名称我们可以发现其中存储了类指针、实例方法表、类方法表、协议表、属性列表,但是并没有类中有的成员变量表。其实看到这里我们就可以明白,我们不可以在分类中定义成员变量,原因很简单,这里面都没有成员变量表。
这里还有一个结论:分类可以声明属性,并可以生成对应的set、get方法,但没有去实现该方法
分类加载流程:
- 在编译阶段将分类中的方法、属性等编译到一个数据结构
category_t
- 将分类中的方法、属性等合并到一个大数组中去,而后参加编译的分类就会在数组前面
- 将合并后的分类数据插入到原有数据的前面
故而当分类中的方法与原始类中方法重名的时候,会先去调用分类中实现的方法。
扩展
@interface Person ()@property (nonatomic, assign) NSInteger age; // 私有属性- (BOOL)validateAge; // 私有方法声明@end
这里我们将一个扩展直接使用Clang
转化位cpp文件,我们可以看到其直接被存储到了成员变量表中,同时方法也直接被添加到了metholist
中:
故而扩展是在编译阶段与该类同时编译的,是类的一部分。扩展中声明的方法只能在该类的@implementation中实现。所以这也就意味着我们无法对系统的类使用扩展。
扩展和分类的区别
类别、分类
- 专门用来给类添加新的方法
- 不能给类添加成员属性,添加了成员属性也无法取到
- 注意:其实可以通过
runtime
给分类添加属性,即属性关联
,重写setter
、getter
方法
- 注意:其实可以通过
- 分类中用
@property
定义变量,只会生成变量的setter
、getter
方法的声明
,不能生成方法实现和带下划线的成员变量
扩展
- 可以说成是
特殊的分类
,也可称作匿名分类
- 可以
给类添加成员属性
,但是是私有变量
- 可以
给类添加方法
,也是私有方法
关联对象
这里我们来讲解一下如何通过runtime
来给分类添加属性,这里主要分为两部分:
- 通过
objc_setAssociatedObject
设值流程 - 通过
objc_getAssociatedObject
取值流程
流程如上所示
我们先来看看取值流程:
objc_setAssociatedObject(id _Nonnull object, const void * _Nonnull key,id _Nullable value, objc_AssociationPolicy policy)
- 参数一:要关联的对象,即为谁添加关联属性
- 参数二:标识符,方便下次查找
- 参数三:value
- 参数四:属性的策略,即
nonatomic、atomic、assign
等,下面展示一下所有关联对象的属性类型:
下面我们来看看objc_setAssociatedObject
的源码实现:
下面我们进入_object_set_associative_reference
源码实现来看看:
void
_object_set_associative_reference(id object, const void *key, id value, uintptr_t policy)
{// This code used to work when nil was passed for object and key. Some code// probably relies on that to not crash. Check and handle it explicitly.// rdar://problem/44094390if (!object && !value) return;if (object->getIsa()->forbidsAssociatedObjects())_objc_fatal("objc_setAssociatedObject called on instance (%p) of class %s which does not allow associated objects", object, object_getClassName(object));//object封装成一个数组结构类型,类型为DisguisedPtrDisguisedPtr<objc_object> disguised{(objc_object *)object};//相当于包装了一下 对象object,便于使用// 包装一下 policy - valueObjcAssociation association{policy, value};// retain the new value (if any) outside the lock.association.acquireValue();//根据策略类型进行处理bool isFirstAssociation = false;{//初始化manager变量,相当于自动调用AssociationsManager的析构函数进行初始化AssociationsManager manager;//并不是全场唯一,构造函数中加锁只是为了避免重复创建,在这里是可以初始化多个AssociationsManager变量的AssociationsHashMap &associations(manager.get());//AssociationsHashMap 全场唯一if (value) {auto refs_result = associations.try_emplace(disguised, ObjectAssociationMap{});//返回结构为一个类对if (refs_result.second) {//判断第二个存不存在,即bool值是否为true/* it's the first association we make */isFirstAssociation = true;}/* establish or replace the association */auto &refs = refs_result.first->second;//得到一个空的桶子,找到引用对象类型,即第一个元素的second值auto result = refs.try_emplace(key, std::move(association));//查找当前的key是否有association关联对象if (!result.second) {//如果结果不存在association.swap(result.first->second);}} else {//如果传的是空值,则移除关联,相当于移除auto refs_it = associations.find(disguised);if (refs_it != associations.end()) {auto &refs = refs_it->second;auto it = refs.find(key);if (it != refs.end()) {association.swap(it->second);refs.erase(it);if (refs.size() == 0) {associations.erase(refs_it);}}}}}// Call setHasAssociatedObjects outside the lock, since this// will call the object's _noteAssociatedObjects method if it// has one, and this may trigger +initialize which might do// arbitrary stuff, including setting more associated objects.if (isFirstAssociation)object->setHasAssociatedObjects();// release the old value (outside of the lock).association.releaseHeldValue();//释放
}
我们来看看这段源码的实现过程:
- 首先检查对象所属类是否禁止关联对象(系统类就不可以),若禁止则直接触发崩溃
- 创建一个全局管理关联对象的
AssociationsManager
管理类,并获取唯一的全局静态哈希Map:AssociationsHashMap
- value是否存在:
- 若存在,通过
try_emplace
方法,创建一个空的ObjectAssociationMap
去取查询键值对 - 如果发现没有这个
key
就插入一个空的BucketT
进去并返回true
- 通过
setHasAssociatedObjects
方法标记对象存在关联对象
即置isa
指针的has_assoc
属性为true
- 用当前
policy 和 value
组成了一个ObjcAssociation
替换原来BucketT
中的空 - 标记一下
ObjectAssociationMap
的第一次为false
AssociationsManager
我们先来看看其源码实现
这里我们可以看到AssociationsHashMap
从静态变量中取出,所以全场唯一
下面我们来看看这AssociationsHashMap
以及ObjectAssociationMap
的定义
这里先说一下
DenseMap
,这个东西时LLVM实现的高性能哈希表,支持快速插入、查找、删除(笔者具体也不会)
- 先来看看
ObjectAssociationMap
,他对应的是一个对象的关联属性集合,通过健快速定位到具体的ObjcAssociation
。
这里展示一下该结构体内部包含的内容:关联值的引用计数策略与实际值
- 再来看看
AssociationsHashMap
,这是一个全局管理所有对象的关联属性的集合,这里键为伪装指针(DisguisedPtr
),值为该对象关联属性表ObjectAssociationMap
这里附一张图来讲解这几个表之间的关系
下面来说一下这几个map之间的联系与不同:
AssociationsManager
可以有很多个,但是AssociationsHashMap
类型的map只能有一个,是通过AssociationsManager
来获取的- 这个map中有很多个
ObjectAssociationMap
类型的map,在上文中的讲解中,我们可以明白每个对象都有一个ObjcAssociation
,所以每个对象都会有一个自己的ObjectAssociationMap
类型的map
key的几种用法
- 使用的get方法的@selector作为key
objc_setAssociatedObject(obj, @selector(getter), value, OBJC_ASSOCIATION_RETAIN_NONATOMIC)
objc_getAssociatedObject(obj, @selector(getter))
- 使用指针的地址作为key
static void *MyKey = &MyKey;
objc_setAssociatedObject(obj, MyKey, value, OBJC_ASSOCIATION_RETAIN_NONATOMIC)
objc_getAssociatedObject(obj, MyKey)
- 使用static作为key
static char MyKey;objc_setAssociatedObject(obj, &MyKey, value, OBJC_ASSOCIATION_RETAIN_NONATOMIC)
objc_getAssociatedObject(obj, &MyKey)
- 使用属性名作为key
objc_setAssociatedObject(obj, @“property”, value, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
objc_getAssociatedObject(obj, @“property”);
流程
-
设置关联对象:
-
调用
objc_setAssociatedObject
-
AssociationsManager
查找或创建与目标对象相关的ObjectAssociationMap
-
在
ObjectAssociationMap
中查找或创建对应的ObjcAssociation
。 -
将关联值和存储策略设置到
ObjcAssociation
中。
-
-
获取关联对象:
-
调用
objc_setAssociatedObject
-
AssociationsManager
查找与目标对象相关的ObjectAssociationMap
-
在
ObjectAssociationMap
中查找对应的ObjcAssociation
。 -
返回
ObjcAssociation
中存储的关联值
-
-
移除关联对象:
- 调用
objc_removeAssociatedObjects
或objc_setAssociatedObject
设置为 nil。 AssociationsManager
查找与目标对象相关的ObjectAssociationMap
。- 从
ObjectAssociationMap
中移除对应的`` ObjcAssociation`。 - 如果
ObjectAssociationMap
为空,可能会移除整个映射以释放资源。
- 调用
这个流程其实也就是上文中_object_set_associative_reference
的流程,笔者认为这样理解更好一些,下面再附一张图帮助理解
总结
关联对象就是一个二层哈希的处理,存取的时候都是两层处理,类似于二维数组:
在这里插入图片描述](https://i-blog.csdnimg.cn/direct/f49187f493b9464e990aa734088ed9d9.png)
相关文章:
【iOS】分类、扩展、关联对象
分类、扩展、关联对象 前言分类扩展扩展和分类的区别关联对象key的几种用法流程 总结 前言 最近的学习中笔者发现自己对于分类、扩展相关知识并不是很熟悉,刚好看源码类的加载过程中发现有类扩展与关联对象详解。本篇我们来探索一下这部分相关知识,首先…...
计算机网络学习(一)—— OSI vs TCP/IP网络模型
一、OSI模型(开放系统互联参考模型) OSI(Open Systems Interconnection)模型由ISO(国际标准化组织)在1984年提出,用于标准化网络通信,它将网络通信分为七个层次: 层级名…...
【MySQL成神之路】MySQL查询用法总结
MySQL查询语句全面指南 一、基础查询语句 MySQL中select的基本语法形式 select 属性列表 from 表名和视图列表 [where 条件表达式] [group by 属性名[having 条件表达式]] [order by 属性名[asc|desc]] [limit <offset>,row count] 说明: where子句&…...
攻防世界——Web题 fakebook
首先测试网站的功能,当我注册一个账号时,发现这里的链接: 点进去看到URL: 感觉no这个地方可以尝试一下sql注入 推测应该是数字型注入 发现果然可以进行sql注入, 最终测得列数应该是4列,但当我尝试sql注入…...
【Java微服务组件】异步通信P2—Kafka与消息
欢迎来到啾啾的博客🐱。 记录学习点滴。分享工作思考和实用技巧,偶尔也分享一些杂谈💬。 欢迎评论交流,感谢您的阅读😄。 目录 引言Kafka与消息生产者发送消息到Kafka批处理发送设计消息的幂等信息确保消息送达acks配置…...
AI数字人一体机和智慧屏方案:开启智能交互新纪元
在当今这个信息化飞速发展的时代,AI技术正以前所未有的速度改变着我们的生活方式和工作模式。特别是在人机交互领域,AI数字人的出现不仅极大地丰富了用户体验,也为各行各业提供了前所未有的创新解决方案。本文将重点介绍由广州深声科技有限公…...
10-码蹄集600题基础python篇
题目如上: 这题就是ASCII的转换,直接使用ord就可以 下面是代码: def main():#code here# a1,a2input().split(",")# print(f"The ASCII code of {a1} is {ord(a1)}")# print(f"The ASCII code of {a2} is {ord(a2…...
给几张图片和一段文字,怎么制作成带有语音的视频---php
想用PHP将图片和文字转换成带有语音的视频,想做自动化的视频生成,比如用于广告、演示或者其他需要多媒体处理的场景。 接下来考虑PHP本身的能力。PHP主要是用于服务器端的脚本语言,不太擅长处理多媒体内容,比如视频和语音合成。所…...
vue3中RouterView配合KeepAlive实现组件缓存
KeepAlive组件缓存 为什么需要组件缓存代码展示缓存效果为什么不用v-if 为什么需要组件缓存 业务需求:一般是列表页面通过路由跳转到详情页,跳转回来时,需要列表页面展示上次展示的内容 代码展示 App.vue入口 <script setup lang"…...
NIFI的处理器:ExecuteGroovyScript 2.4.0
ExecuteGroovyScript是常用的处理器之一,用于执行GroovyScript脚本。该脚本负责处理传入的流文件(例如传输到SUCCESS或删除)以及由该脚本创建的任何流文件。如果处理不完整或不正确,会话将被回滚。 属性值-失败处理策略 Failure …...
安全可控的AI底座:灯塔大模型应用开发平台全面实现国产信创兼容适配认证
国产信创产品兼容适配认证是为了支持和推动国产信息技术产品和服务的发展而设立的一种质量标准和管理体系。适配认证旨在确保相关产品在安全性、可靠性、兼容性等方面达到一定的标准,以满足政府和关键行业对信息安全和自主可控的需求。 北京中烟创新科技有限公司&a…...
.NET外挂系列:5. harmony 中补丁参数的有趣玩法(下)
一:背景 1. 讲故事 开局一张表,故事全靠编,为了能够承上启下,先把参数列表放出来。 参数名说明__instance访问非静态方法的实例(类似 this)。__result获取/修改返回值,要想修改用 ref。__res…...
Spring Boot 登录实现:JWT 与 Session 全面对比与实战讲解
Spring Boot 登录实现:JWT 与 Session 全面对比与实战讲解 2025.5.21-23:11今天在学习黑马点评时突然发现用的是与苍穹外卖jwt不一样的登录方式-Session,于是就想记录一下这两种方式有什么不同 在实际开发中,登录认证是后端最基础也是最重要…...
vscode离线安装组件工具vsix
1.外网下载vsix 网址为:Open VSX Registry 2.输入需要下载的组件 3.下载组件 4.安装 5.选择安装文件 6.安装完成...
Vue大数据量前端性能优化策略
文章目录 前言Vue大数据量前端性能优化策略1. 虚拟列表的使用方式及优势2. 列表和图表的懒加载技术3. Web Worker 在图表数据预处理中的应用4. 图表渲染优化技巧5. 分批渲染技术实现方法(如 requestIdleCallback)6. 其他可行的 Vue 层优化策略 前言 Vue…...
Hass-Panel - 开源智能家居控制面板
文章目录 ▎项目介绍:预览图▎主要特性安装部署Docker方式 正式版Home Assistant Addon方式详细安装方式1. Home Assistant 插件安装(推荐)2. Docker 安装命令功能说明 :3. Docker Compose 安装升级说明Docker Compose 版本升级 功…...
iPaaS集成平台技术选型关注哪些指标?
在数字化转型进程中,企业系统间的数据孤岛问题日益凸显。根据IDC调研,85%的IT决策者将“系统集成效率”列为业务创新的关键瓶颈。iPaaS(集成平台即服务)凭借其敏捷性、低代码特性和智能化能力,已成为企业构建数字生态的…...
JavaScript性能优化实战(14):跨端JavaScript性能优化
在当今多端开发的时代,JavaScript已经突破了浏览器的界限,广泛应用于移动应用、桌面应用、小程序等各类环境。然而,不同平台的运行时环境存在差异,为JavaScript性能优化带来了新的挑战和思考维度。 目录 React Native性能优化最佳实践Electron应用性能优化策略混合应用中J…...
多通道经颅直流电刺激器产品及解决方案特色解析
前记 团队在多通道经颅直流电刺激这个技术方向,一路深耕。在服务了不少客户之后,为了方便后续的产品和方案推广。我们弄出来了产品和方案两种形态。标准产品是为了给用户演示以及一些常规的实验使用。方案则是为了满足不同方向的科研用户的需求。这两者相…...
Quasar 使用 Pinia 进行状态管理
官方文档:使用 Pinia 进行状态管理 |Quasar 框架 视频教程:quasar框架store-状态管理库pinia介绍_哔哩哔哩_bilibili 使用 Quasar CLI 创建一个新的store quasar new store date --format jsPinia存储模板详解解 基本结构解析 import { defineStore,…...
计算机网络--第一章(下)
1.计算机网络的分层结构 1.1 分层结构 网络体系结构描述的是,计算机网络有几层,有什么功能,用的什么协议。 水平方向的关系, 协议,说的是对等实体间通信需要遵守的规则。用于约束,这个约束的方向是水平的。…...
Veo 3 可以生成视频,并附带配乐
谷歌最新的视频生成 AI 模型 Veo 3 可以创建与其生成的剪辑相配的音频。 周二,在谷歌 I/O 2025 开发者大会上,谷歌发布了 Veo 3。该公司声称,这款产品可以生成音效、背景噪音,甚至对话,为其制作的视频增添配乐。谷歌表…...
数据结构核心知识总结:从基础到应用
数据结构核心知识总结:从基础到应用 数据结构是计算机科学中组织和存储数据的核心方式,直接影响程序的性能和资源利用率。本文系统梳理常见数据结构及其应用场景,帮助读者构建清晰的知识体系。 一、数据结构基础概念 数据结构是数据元素之间…...
Flannel后端为UDP模式下,分析数据包的发送方式(二)
发往 10.244.2.5 的数据包最终会经过物理网卡 enp0s3,尽管路由表直接指定通过 flannel.1 发出。以下以 Markdown 格式详细解释为什么会经过 enp0s3,结合 Kubernetes 和 Flannel UDP 模式的背景。 问题分析 在 Kubernetes 环境中,使用 Flanne…...
超低延迟音视频直播技术的未来发展与创新
引言 音视频直播技术正在深刻改变着我们的生活和工作方式,尤其是在教育、医疗、安防、娱乐等行业。无论是全球性的体育赛事、远程医疗、在线教育,还是智慧安防、智能家居等应用场景,都离不开音视频技术的支持。为了应对越来越高的需求&#x…...
改写视频生产流程!快手SketchVideo开源:通过线稿精准控制动态分镜的AI视频生成方案
Sketch Video 的核心特点 Sketch Video 通过手绘生成动画的形式,将复杂的信息以简洁、有趣的方式展现出来。其核心特点包括: 超强吸引力 Sketch Video 的手绘风格赋予了视频一种质朴而真实的质感,与常见的精致特效视频形成鲜明对比。这种独…...
Circle宣布Circle Payments Network主网上线
据 Circle 官方消息,Circle Payments Network 主网正式上线。该网络是一个基于区块链的支付协调协议,允许银行和支付服务提供商使用公共区块链上的 USDC 进行实时结算。 Circle Payments Network 支持企业对企业供应商支付、跨境汇款、资金管理、企业定期…...
【RabbitMQ】记录 InvalidDefinitionException: Java 8 date/time type
目录 1. 添加必要依赖 2. 配置全局序列化方案(推荐) 3. 配置RabbitMQ消息转换器 关键点说明 1. 添加必要依赖 首先确保项目中包含JSR-310支持模块: <dependency><groupId>com.fasterxml.jackson.datatype</groupId>&l…...
linux 学习之位图(bitmap)数据结构
bitmap 可以高效地表示大量的布尔值,并且在许多情况下可以提供快速的位操作。 1 定义 enum device_state{DOWN,DOEN_DONE,MAILBOX_READY,MAILBOX_PENDING,STATE_BUILD };DECLARE_BITMAP(state,STATE_BUILD);相当于》u32 state[BITS_TO_LONGS(4)] BIT…...
CNN手写数字识别/全套源码+注释可直接运行
数据集选择: MNIST数据集来自美国国家标准与技术研究所, National Institute of Standards and Technology (NIST)。训练集(training set)由来自250个不同人手写的数字构成,其中50%是高中学生,50%来自人口普查局&…...
基于springboot+vue网页系统的社区义工服务互动平台(源码+论文+讲解+部署+调试+售后)
感兴趣的可以先收藏起来,还有大家在毕设选题,项目以及论文编写等相关问题都可以给我留言咨询,我会一一回复,希望帮助更多的人。 系统背景 在社会文明程度不断提升、社区治理需求持续深化的大背景下,社区义工服务作为…...
MBSS-T1:基于模型的特定受试者自监督运动校正方法用于鲁棒心脏 T1 mapping|文献速递-深度学习医疗AI最新文献
Title 题目 MBSS-T1: Model-based subject-specific self-supervised motion correction forrobust cardiac T1 mapping MBSS-T1:基于模型的特定受试者自监督运动校正方法用于鲁棒心脏 T1 mapping 01 文献速递介绍 心脏T1定量成像(Quantitative Car…...
Google机器学习实践指南(迭代学习机制解析篇)
🔥 Google机器学习(5)-迭代学习机制解析 Google机器学习实战(5)-深入理解模型训练中的迭代优化过程 一、迭代学习概念 ▲ 核心定义: 在训练机器学习模型时,首先对权重和偏差进行初始猜测,然后反复调整这些猜测,直到…...
【时时三省】Python 语言----文件
目录 1,文件打开 2, 文件关闭 3, 文件写入 4, 文件读出 5, 文件定位 6, 文件重命名 7, 复制文件 山不在高,有仙则名。水不在深,有龙则灵。 ----CSDN 时时三省 1,文件打开 file = open(file, mode, buffering, encoding, errors, newline, closefd, opener) 2, 文…...
WPF···
设置启动页 默认最后一个窗口关闭,程序退出,可以设置 修改窗体的icon图标 修改项目exe图标 双击项目名会看到代码 其他 在A窗体点击按钮打开B窗体,在B窗体设置WindowStartupLocation=“CenterOwner” 在A窗体的代码设置 B.Owner = this; B.Show(); B窗体生成在A窗体中间…...
架构图 C4 规范简介
架构图 C4 规范简介 C4(Context, Containers, Components, Code)是一种用于软件架构可视化的分层建模方法,由 Simon Brown 提出。它通过四个不同层次的抽象来描述软件系统,适用于不同受众(如业务人员、架构师、开发人…...
运维Web服务器核心知识与实战指南
一、Web服务器基础概述 (一)核心定义与功能 Web服务器是互联网的基础设施,负责存储、处理和传输网页内容,通过HTTP/HTTPS协议与客户端交互。其核心功能包括: 请求处理:监听端口(默认80/443&a…...
免费建站系统是什么?如何选择免费建站系统?
如今,换互联网成为大家生活中必不可少的一部分。对于普通的个人、一些企业、包括一些事业单位,拥有一个高效实用的网站成为展示、宣传、产品介绍的重要途径。但是对于很多用户来说,对于一些没有建站基础的用户来说:建站是一项高门…...
React---day1
React 它允许我们只需要维护自己的状态,当状态改变时,React可以根据最新的状态去渲染我们的UI界面 开发React必须依赖三个库: eact:包含react所必须的核心代码react-dom:react渲染在不同平台所需要的核心代码babel&…...
赋能智慧党建:远眺科技助力党校可视化系统高效落地
项目背景:智慧党校建设的时代召唤 在数字化浪潮席卷各行各业的今天,传统党校亦面临转型升级的迫切需求。 宁波某地党校,积极响应国家关于推进“智慧党建”的号召,旨在通过引入先进信息技术,打造一个集数据展示、信息…...
解决使用HBuilder X开发时uView组件不生效的问题
1.uni-ui 是一个为 uni-app 开发的 UI 组件库,你可以通过 npm 安装它。 在项目的根目录下打开终端(可以通过菜单“工具” > “终端”打开),然后运行以下命令来安装 uni-ui: npm install uview-ui2.安装后ÿ…...
React中 lazy与 Suspense懒加载的组件
MyHead.jsx console.log(MyHead.jsx); function Head() {return <>hello Head</>; } export default Head;懒加载.jsx // 引入 React 的 useState、lazy 和 Suspense API // lazy 用于懒加载组件,Suspense 用于在加载过程中显示 loading 状态 import …...
网络学习-利用reactor实现http请求(六)
一、实现HTTP请求 1、印象里面,总有人说C/C语言不能实现HTTP请求,其实不然。C/C语言完全可以实现HTTP请求。通过对select,poll,epoll等IO多路复用技术的学习以及reactor模式的学习,完全能够实现HTTP请求。 2、webserver 主要解决两个问题 …...
【东枫科技】usrp rfnoc 开发环境搭建
作者 太原市东枫电子科技有限公司 ,代理销售 USRP,Nvidia,等产品与技术支持,培训服务。 环境 Ubuntu 20.04 依赖包 sudo apt-get updatesudo apt-get install autoconf automake build-essential ccache cmake cpufrequtils …...
RabbitMQ的其中工作模式介绍以及Java的实现
文章目录 前文一、模式介绍1. 简单模式2. 工作队列模式3. 广播模式4. 路由模式5. 通配符模式6. RPC模式7. 发布确认模式 二、代码实现1、简单模式2、工作队列模式生产者消费者消费者 1消费者 2 3、广播模式 (Fanout Mode)生产者消费者 4、路由模式 (Direct Mode)生产者消费者 5…...
Docker 镜像打包到本地
保存镜像 使用 docker save 命令将镜像保存为一个 tar 文件。命令格式如下: docker save [options] IMAGE [IMAGE...]示例:docker save -o centos.tar centos:latest--output 或 -o:将输出保存到指定的文件中。 加载镜像 如果需要在其他机器…...
5分钟搭建智能看板:衡石科技自助式BI工具使用教程
在数据驱动的时代,业务人员需要快速将数据转化为洞察,而非依赖IT团队排队开发报表。衡石科技HENGSHI SENSE的自助式BI工具,通过零代码配置、模板化设计、智能分析三大核心能力,让任何人都能在5分钟内搭建专业级数据看板。本文将手…...
安卓开发用到的设计模式(1)创建型模式
安卓开发用到的设计模式(1)创建型模式 文章目录 安卓开发用到的设计模式(1)创建型模式1. 单例模式(Singleton Pattern)2. 工厂模式(Factory Pattern)3. 抽象工厂模式(Abs…...
Unity3D序列化机制详解
前言 Unity3D的序列化机制是其编辑器与运行时数据管理的核心,理解其工作原理对高效开发至关重要。以下是关键点总结: 对惹,这里有一个游戏开发交流小组,希望大家可以点击进来一起交流一下开发经验呀! 1. 序列化的作…...
[Harmony]自定义导航栏
1.方案一 CustomNavigationBar import { router } from kit.ArkUI; import { DevicesUtil } from ../utils/DevicesUtil; import { common } from kit.AbilityKit;Component export struct CustomNavigationBar {State private navHeight: number 44State parTitle: string …...