type
status
date
slug
summary
tags
category
icon
password
本文主要研究Tagged Pointer技术,针对该技术需要解决的问题、以及在实际应用中的价值做一些简单的探讨。
如果你想要更进一步,去挖掘Tagged Pointer是如何实现的,可以参考Friday Q&A 2012-07-27: Let's Build Tagged Pointers和objc源码。
另外,本文中涉及到的示例代码,请在真机iOS设备上测试,因为Tagged Pointer技术针对不同的平台,具体实现细节是有差异的,否则无法得出和本文一致的测试结果。
一、对象的内存
下面我们针对iOS中对象进行一些探究,代码如下,其完整代码见TaggedPointer。
在第7行,首先定义了4个
__weak***
对象,构建了一个autoreleasepool,所以在12行之后,所有__weak
修饰的弱引用对象,都会被释放。经过上面分析,我们得出,对象会打印出null
。但是,实际上,我们得到了如下的输出。
TaggedPointer[3570:3928309] weakObj is (null)
TaggedPointer[3570:3928309] weakNumber is 123
TaggedPointer[3570:3928309] weakString is string123
TaggedPointer[3570:3928309] weakDate is Thu Jan 1 08:00:00 1970
可以看到,只有NSObject对应的对象值是null,其他的值,均正常打印。
这是因为
NSNumber
、NSString
、NSDate
,在这里采用了Tagged Pointer技术。二、Tagged Pointer
2.1 Tagged Pointer技术
2.1.1 简介
![notion image](https://wiki-1259056568.cos.ap-shanghai.myqcloud.com/ios/20190603201832.png?t=d5bf7563-7631-4de2-8723-a37c5b0c9d21)
2.2.2 未引入Tagged Pointer
![notion image](https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2Ff283ca8c-3a00-40dd-87c9-43c248d44a31%2F3d66cd01-70ee-41ab-8939-994bb7765cd4%2FUntitled.png?table=block&id=d8a6f588-38f2-4091-889f-e003833d790a&t=d8a6f588-38f2-4091-889f-e003833d790a&width=768&cache=v2)
2.2.3 引入Tagged Pointer
![notion image](https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2Ff283ca8c-3a00-40dd-87c9-43c248d44a31%2F72718e65-4573-4eb1-808f-2e4083a47466%2FUntitled.png?table=block&id=d8c39755-e9ef-493b-bb64-209ad1d35570&t=d8c39755-e9ef-493b-bb64-209ad1d35570&width=816&cache=v2)
2.2.4 判断是否是Tagged Pointer
![notion image](https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2Ff283ca8c-3a00-40dd-87c9-43c248d44a31%2F77b5ca93-3bb7-4f44-9b84-15b9371ddf55%2FUntitled.png?table=block&id=d9fd0bd0-b2c8-44b9-9338-8371905d65fd&t=d9fd0bd0-b2c8-44b9-9338-8371905d65fd&width=816&cache=v2)
2.2 应用
2.2.1 支持的对象类型
可以从objc源码中找出支持Tagged Pointer 的对象类型,如下:
即针对
NSString
、NSNumber
、NSDate
、NSIndexPath
这些类型,都支持Tagged Pointer技术。2.2.2 NSNumber
我们通过
NSNumber
以及NSString
对象来观察Tag+Data的存储形式。示例代码参见:TaggedPointer
如下所示,我们创建了很多
NSNumber
对象:由上表我们得出:
- 很大的数字,超过Tagged Pointer表示上限的时候,将会转为对象存储,存放在堆上;
- 如果是含有小数点的浮点数,将会直接以对象方式存储;
- 其余类型的数字,包括不含小数部分的浮点型和整型都会以Tagged Pointer存储。
并且,针对以上部分,我们整理出Tagged Pointer的存储格式如下,以number1为例:
![notion image](https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2Ff283ca8c-3a00-40dd-87c9-43c248d44a31%2F71561425-99ba-4f92-985e-e48b053aad19%2FUntitled.png?table=block&id=3a3ced4c-927e-4fd6-be35-88bad4ef41f6&t=3a3ced4c-927e-4fd6-be35-88bad4ef41f6&width=768&cache=v2)
2.2.3 NSString
同上面
NSNumber
的处理逻辑,NSString
处理的类似。根据以上结果,我们将NSString分类三类:
- 常量类型:__NSCFConstantString,定义的字符串常量。
- Tagged Pointer类型:NSTaggedPointerString,通过对象方法创建的短字符串。
- NSString对象类型:__NSCFString,包括NSString、NSMutableString等创建的字符串对象。
以上,整理如下:
![notion image](https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2Ff283ca8c-3a00-40dd-87c9-43c248d44a31%2F11e0f5bb-c7bb-49f8-a535-e723b8f54d60%2FUntitled.png?table=block&id=40e0d1c4-b28f-431d-a29f-cb62c0971a9c&t=40e0d1c4-b28f-431d-a29f-cb62c0971a9c&width=720&cache=v2)
NSString以Tagged Pointer的存储格式如下:
![notion image](https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2Ff283ca8c-3a00-40dd-87c9-43c248d44a31%2F24dfef8e-daa5-4199-9de6-67bef1844671%2FUntitled.png?table=block&id=52f81429-09db-45e1-816c-b549b2b8b447&t=52f81429-09db-45e1-816c-b549b2b8b447&width=816&cache=v2)
2.3 内存管理
![notion image](https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2Ff283ca8c-3a00-40dd-87c9-43c248d44a31%2F90ea473d-e142-4b22-a035-b12ed4826284%2FUntitled.png?table=block&id=274ce52a-ae40-4289-b706-66fdaceab2d7&t=274ce52a-ae40-4289-b706-66fdaceab2d7&width=720&cache=v2)
三、一个面试问题的研究
该面试题如下:
![notion image](https://www.notion.so/image/https%3A%2F%2Fprod-files-secure.s3.us-west-2.amazonaws.com%2Ff283ca8c-3a00-40dd-87c9-43c248d44a31%2F3c4eaf8d-c04b-4861-a33e-402b0551d8ec%2FUntitled.png?table=block&id=fb833e89-9c50-49ff-950c-8a31309c0e94&t=fb833e89-9c50-49ff-950c-8a31309c0e94&width=816&cache=v2)
参考
链接
示例代码