objc里的伪指针TaggedPointer

如果你看过我前面两篇objc函数枢纽msgSend你印象中的NSString是这样吗,相信已经多次看过它的身影了,到底它是何物何作用,我今日就来揭开谜团。
我之所为称呼它为伪指针,是因为它像幽灵一样,没有肉身(实例)但却在能像objc对象实例那样表现出各种行为。你能猜出下面代码运行的结果吗?

// non-arc
id unknown = (id)0x12345678;
NSLog(@"%@", unknown);
unknown = (id)0xa000000000032312;
NSLog(@"%@", unknown);
NSString* s12 = [NSString stringWithUTF8String:"12"];
NSLog(@"%@", s12);
[s12 isEqualToString:unknown];
NSLog(@"%d", *(int64_t*)&s12 == *(int64_t*)&unknown);

如果我随便编写一个地址0x12345678,然后用这个地址进行objc调用,[(id)0x12345678 retain]。相信大家第一反应是我正在对一个不明白的地址访问,指向这个地址的指针大家叫它野指针,我正在向一个“野指针”操作。

如果我又随便编写一个地址像这们0xa000000000032312,并对这个地址进行objc调用[(id)0xa000000000032312 retain]。相信大家的反应是和上面举例的情况一样,尽管当中有人看过我们前面的文章知道这是一个TaggedPointer,但是我还是在对一个不可信的地址进行操作,当访问0xa000000000032312内存地址的内容时将要出错。

但结果却是,0xa000000000032312地址的操作合法,并且用NSLog(@"%@", (id)0xa000000000032312)还打印出12。

大家都熟悉实例的构建过程,如[[NSString alloc] init]和[NSString string]。都必须为对像实例分配空间然后初始化。然而地址0xa000000000032312只是我随便编造的,完全没有在那个地址上分配过空间。
我再来调用[NSString stringWithUTF8String:"12"],返回了一个类型是NSTaggedPointerString实例的指针。指向的地址正是0xa000000000032312。直到这时0xa000000000032312的实例才被构建,然而对这个地址一访问还是一个非法地址。

所以TaggedPointer只是一个伪指针,它的真相就在这个指针指向的地址的数值本身。
0xa000000000032312这个数值就像一个被压缩的对像实例一样,最高4位是isa的线索,参考前面介绍反汇编msgSend文章,最低8位是info信息,中间第9位起的48位是对像的content。用这副幽灵镜来再看0xa000000000032312,什么都一清二楚了,{isa=0xa,coutent='\x31\x32',len=2}。这是NSString中一种名为EightBitsEncoding的情况。

为什么要有TaggedPointer,就让我们来看一下性能。
用profile分别查看循环100M次的[@"ab" stringAppendByString:@"c"]和[NSString stringWithUTF8String:"abc"];
上一篇的例子可以找到[@"ab" stringAppendByString:@"c"]返回__NSCFString, [NSString stringWithUTF8String:"abc"]返回NSTaggedPointerString。
究竟它们之间有什么样的性能差别呢?由于我的机器性能有限,profile时几近运行不过来,所以没有图可截贴出,只能陈述一下情况。先是[@"ab" stringAppendByString:@"c"]返回__NSCFString的情况,CFString不断地在缓慢分配,待到分配了1M个时,内存占用了50M,机器在profile运行中惨不忍睹,我果断中止了。另一方面[NSString stringWithUTF8String:"abc"]返回NSTaggedPointerString的profile中,CFString数量没有增长,内存自然也没有消耗。好我将循环次数减少至1M次,不做profile,直接运行对比,NSTaggedPointerString的情况明显要快出几倍,因为根本没有构建过实例(,用于返回的实例,中间里面的过程一样还有其它临时实例的)。

除了NSTaggedPointerString还有其它的TaggedPointer,你知道0xb0000000000000c2是什么吗,赶紧试一试。

最后多谢大家再次观看。

转载于:https://www.cnblogs.com/bbqzsl/p/5118905.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: objc app架构是一种基于Objective-C语言开发的应用程序架构。在这种架构中,应用程序的主要组成部分是由Objective-C编写的对象,这些对象封装了应用程序的业务逻辑和功能。 在objc app架构中,主要包含以下几个关键的组件: 1. 模型(Model):模型是应用程序的数据和业务逻辑的核心。在objc app架构中,模型通常由Objective-C类实现,用于封装数据和处理相关的业务逻辑。 2. 控制器(Controller):控制器负责协调模型和视图之间的交互。它接收用户的输入,并将其传递给模型进行处理,然后更新视图以显示结果。控制器通常是Objective-C类,用于处理应用程序的逻辑控制和事件处理。 3. 视图(View):视图是应用程序的用户界面的可视化表示。它负责显示模型中的数据,并将用户的输入传递给控制器进行处理。在objc app架构中,视图通常是由UIKit或Cocoa Touch框架提供的界面元素,如按钮、标签、文本框等。 通过以上三个组件的协同工作,objc app架构实现了应用程序的分层架构,将数据、逻辑和界面分离开来,提高了代码的可维护性和复用性。此外,objc app架构还支持面向对象编程的特性,如封装、继承和多态,以及设计模式的使用,如MVC(Model-View-Controller)模式,从而进一步提高了应用程序的开发效率和质量。 总而言之,objc app架构是一种基于Objective-C语言的应用程序架构,通过模型、控制器和视图的协同工作,实现了数据、逻辑和界面的分离,提高了应用程序的可维护性和复用性。 ### 回答2: ObjC App架构是iOS应用开发中的一种常见的架构模式。它由iOS开发者王巍所提出,旨在提供一种清晰、可扩展和易于维护的应用架构。 ObjC App架构的核心思想是将应用分解成相互独立的模块,每个模块负责特定的功能。这些模块之间通过协议和委托进行通信,实现了低耦合和可测试性。常见的模块有View、ViewModel和Model。 View层负责用户界面的展示和用户交互的响应。View层主要由ViewController组成,负责将用户的操作传递给ViewModel,并将ViewModel返回的数据展示给用户。此外,View层还包括了View和ViewModel之间的绑定,实现了双向数据绑定。 ViewModel层是View层和Model层之间的桥梁,负责处理业务逻辑和数据的转换。ViewModel层通常包含了与网络请求、数据解析和数据处理相关的代码。ViewModel将Model层的数据转换成View所需的格式,并将用户的操作转发给Model层。 Model层负责数据的存储和获取。它可以包含网络请求、数据库操作、数据解析等功能。Model层的设计应尽量简单,只关注数据的读写,而不涉及业务逻辑。 通过使用ObjC App架构,我们可以将应用的不同功能模块分解成独立的部件,使得代码更加清晰和易于维护。同时,模块之间低耦合的设计也提高了代码的扩展性和可测试性。此外,ObjC App架构还可以提高多人协作开发的效率,不同团队成员可以专注于各自负责的模块,降低了代码冲突和合并的难度。 总的来说,ObjC App架构是一种优秀的iOS应用架构模式,它通过分解应用的功能模块,提供了清晰、可扩展和易于维护的代码结构。这种架构模式在iOS开发中得到了广泛应用,并为开发者提供了更好的开发体验和效率。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值