- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章OC runtime学习笔记之关联对象由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
前言 。
objective-c 不能动态的添加一些属性到对象上,和其他的一些原生支持这点的语言不一样。所以之前你都不得不努力为未来要增加的变量预留好空间。在 mac os x 10.6 中,objective-c 的 runtime 已经原生的支持这个功能了.
oc runtime 中关联对象的方法相信大家都使用过,但是其原理和内部实现就很多人不知道。这篇文章就来讲解一下 oc runtime 之关联对象,下面直接步入正题.
runtime 关联对象原理 。
runtime 中提供的 api 如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
/// 对象关联策略
typedef
objc_enum(
uintptr_t
, objc_associationpolicy) {
objc_association_assign = 0,
/**< 关联一个弱引用 */
objc_association_retain_nonatomic = 1,
/**< 指定关联一个强引用. 非原子性. */
objc_association_copy_nonatomic = 3,
/**< 指定关联一个拷贝引用. 非原子性. */
objc_association_retain = 01401,
/**< 指定关联一个强引用.原子性. */
objc_association_copy = 01403
/**< 指定关联一个拷贝引用.原子性. */
};
/**
* 用给定的 key 和关联策略 policy 为指定的 object 设置关联关系
*/
void
objc_setassociatedobject(id object,
const
void
* key, id value, objc_associationpolicy policy);
/**
* 通过给定的 object 和 key 拿到关联的对象
*/
id objc_getassociatedobject(id object,
const
void
* key);
/**
* 移除给定 object 所有关联的关系
*/
void
objc_removeassociatedobjects(id object);
|
runtime 的 api 很简单,实际上工作中使用 runtime 的关联对象也很方便,如下:
1
2
3
4
5
6
7
8
9
10
11
|
static
const
void
* _nonnull titlekey = @
"titlekey"
;
- (
void
)settitle:(nsstring *)title
{
objc_setassociatedobject(self, titlekey, key, objc_association_retain);
}
- (nsstring *)title
{
return
objc_getassociatedobject(self, titlekey);
}
|
如此简单强大的功能,如果想要观察系统的实现,可以找关联对象的源码,我们可以从objc 源码中拿到, 。
从源码中,可以找到以上三个 api 的实现如下:
以 objc_setassociatedobject 方法为例,方法内部调用的一个内部方法,参数同上,进入内部方法 。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
/// 方法为我加过注释的代码。
void
_object_set_associative_reference(id object,
void
*key, id value,
uintptr_t
policy) {
// 取原来的绑定关系,新绑定关系原来关系为空
objcassociation old_association(0, nil);
// 验证参数
id new_value = value ? acquirevalue(value, policy) : nil;
{
// 内部绑定关系管理器.内部管理一个全局 associationshashmap
associationsmanager manager;
// 管理器中的绑定关系map
associationshashmap &associations(manager.associations());
// 生成伪装地址。处理参数 object 地址
disguised_ptr_t disguised_object = disguise(object);
if
(new_value) {
// 打破原来存在的绑定关系
associationshashmap::iterator i = associations.find(disguised_object);
// 以伪装地址为key 在associationshashmap找objc 对应的二级 map
if
(i != associations.end()) {
// 二级map存在。并取二级map: objectassociationmap
objectassociationmap *refs = i->second;
// 同样的方法找到 objectassociationmap 中绑定关系
objectassociationmap::iterator j = refs->find(key);
// 通过key 在objectassociationmap 中找objcassociation
if
(j != refs->end()) {
// 找到原来 objcassociation 关系,直接赋值old_association
old_association = j->second;
j->second = objcassociation(policy, new_value);
}
else
{
// 不存在 -> 重新创建一次
(*refs)[key] = objcassociation(policy, new_value);
}
}
else
{
// 不存在二级map 就直接从新创建
objectassociationmap *refs =
new
objectassociationmap;
associations[disguised_object] = refs;
(*refs)[key] = objcassociation(policy, new_value);
object->sethasassociatedobjects();
}
}
else
{
// 未传 value ,直接设置关联关系为nil。移除原来的绑定关系
associationshashmap::iterator i = associations.find(disguised_object);
if
(i != associations.end()) {
objectassociationmap *refs = i->second;
objectassociationmap::iterator j = refs->find(key);
if
(j != refs->end()) {
old_association = j->second;
refs->erase(j);
}
}
}
}
// 释放 old value.
if
(old_association.hasvalue()) releasevalue()(old_association);
}
|
从源码中可以看到维护对象关联的对象主要有四个 。
associationsmanager // 维护关联关系的全局管理者 ---> 保存associationshashmap associationshashmap // 保存关联关系的hashmap ---> 保存对象对应的关联关系的map objectassociationmap // 对象关联关系的map,二级map objcassociation // 关联关系 。
它们的关系用图像表示如下:
runtime 。
相当于从我们的对象外部重新创建并管理了一套对象关联机制,通过双层 hashmap 来维护对象之间的关联关系。其中 associationshashmap(外层map)是存放在 associationsmanager 中的全局静态 map。通过要关联对象的内存地址处理得到和对象唯一绑定的 key 在 map 中保存和对象相关的objectassociationmap,此 map 又维护一个一个的 objcassociation (关联策略和值).
以上以 objc_setassociatedobject 为例讲解了关联对象的原理,objc_getassociatedobject和objc_removeassociatedobjects 原理也是一样.
思维拓展 。
runtime 中对象关联的原理如上,学习了苹果源码中的思想。可以发现工作中很多类似的数据存储恰好能借鉴一下.
恰好下午研究 runtime 对象关联原理的时候,朋友问我一个多用户系统的实现逻辑.
大意是:
看到这个问题,我直接感觉 runtime 中对象关联的实现恰好就是这个问题的极好实现.
通过用户登录id为 key 创建用户信息map。确定每个用户id对应唯一一个用户信息表,用户信息表中想保存什么信息就自定义啦.
总结 。
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对我的支持.
原文链接:http://www.cnblogs.com/xiaoyouPrince/p/9648195.html 。
最后此篇关于OC runtime学习笔记之关联对象的文章就讲到这里了,如果你想了解更多关于OC runtime学习笔记之关联对象的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
基于 Docker 镜像在 OpenShift 上创建新应用程序的语法有点令人困惑: Usage: oc new-app (IMAGE | IMAGESTREAM | TEMPLATE | PAT
前言 objective-c 不能动态的添加一些属性到对象上,和其他的一些原生支持这点的语言不一样。所以之前你都不得不努力为未来要增加的变量预留好空间。在 mac os x 10.6 中,obje
我正在使用cloudformation脚本,我成功执行oc login -u user -p password 我的脚本继续进行,一段时间后我遇到了问题,因为我好像没有登录过。$(oc whoami)
尝试绘制“^ oC”,但不断出现错误:“错误:“ggplot”中出现意外的“^” 但是,如果我放置“R ^ {o} C”是可行的。请参阅下面的代码段。第一个代码不起作用,第二个代码不起作用,但是对于y
我想根据特定部署为 openshift 模板提供一组不同的参数。我一直在使用 oc new-app -f my-template.yml -p P1="p1-override-value" -p P2
1.每个对象只有哈希值,不等于其他对象? NSObject *obj1 = [[NSObject alloc] init]; NSObject *obj2 = [[NSObject alloc] in
这里有两种方法那个更好?没看懂... 谢谢! - (void)setName:(NSString *)name { //one way [_name release]; [na
我正在尝试在本地 Virtualbox centos 7.4 上设置 openshift origin。这是一个仅用于学习目的的多合一环境。我遵循了确切的文件: https://docs.okd.io
我还应该在单元测试中释放对象吗? 我注意到在Apple的“iPhoneUnitTests”示例项目中,设置方法中的对象是[[object alloc] init],但从未在单元测试中的任何地方发布?
我知道 oc tag -d python:3.5将仅删除 3.5 标签。但是我想使用 oc 命令从同一图像流中删除多个旧标签。 例如图像流 phython:rel-1、phython:rel-2、ph
从这个问题你可以看出我是一个新手。 目前为了获取我的 pod 的日志,我正在做一个...... oc logs -f api-myapp-v1-48-cdrs2 这向我显示了日志中的所有内容。我怎么能
我正在为 Sharepoint 构建几个 Web 部件,我需要显示用户的存在(来自 Lync/OCS)。当我使用时: " + user.Name + " 它工作正常,我通过许多功能(姓名、
我有一个工具类。工具类写了lz4解压的方法,但是解压受控,不知道哪里出了问题(libcompression.tbd和#include "compression.h"都有)。下面是代码: + (NSDa
效果图 实现思路 要实现绘图,通常需要自定义一个uiview的子类,重写父类的- (void)drawrect:(cgrect)rect方法,在该方法中实现绘图操作 若想显示下载进度,只需要
我正在尝试 okd,但在 oc 集群向上端口检查步骤中它对我来说失败了。出于礼貌,调试输出不是很冗长。您知道要寻找什么吗? $ oc cluster up Getting a Docker clien
我在 Ubuntu 16.04.3 LTS 上安装了 Docker 和 OpenShift 客户端 [vagrant@desktop:~] $ docker --version Docker vers
有什么区别rhc 和 oc CLI 工具? 正如我所见,他们的做法几乎相同: oc : The OpenShift CLI exposes commands for managing your app
我尝试在 openshift pod 上运行远程命令来删除特定目录中的一些文件,以下命令有效: oc exec mypod -i -t -- rm -f /tmp/mydir/1.txt 但是,我无
当前,我们正在使用以下命令在Openshift中更新configmap设置(此后,我们将重新启动Pod,以使设置生效): oc apply -f configmap.yml 我的问题是: 该命令将删除
怎么把RLMObject转换成NSDictionary? 这是我的代码: NSString *imei = [Utils getUUID]; NSPredicate *pred = [NSPredic
我是一名优秀的程序员,十分优秀!