话题从sunnyxx的《黑幕背后的Autorelease》开始

文章开头有个小例子

__weak id reference = nil;
- (void)viewDidLoad {
[super viewDidLoad];
NSString *str = [NSString stringWithFormat:@"sunnyxx"];
// str是一个autorelease对象,设置一个weak的引用来观察它
reference = str;
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
NSLog(@"%@", reference); // Console: sunnyxx
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
NSLog(@"%@", reference); // Console: (null)
}

测试以后发现三个方法中都输出了字符串”sunnyxx“,实际上sunnyxx对autorelease的分析还是很准确深刻的,输出结果不符合预期,是NSString在搞怪。

NSString是一个类簇(Class Clusters),最后生成的对象类型,取决于我们调用的初始化方法。不同的对象类型的管理方式不一样(在retainCount上有所体现)

类型 初始化后的retaincount
__NSCFConstantString -1
__NSCFString 1
__NSTaggedPointerString -1
  • 对于__NSCFConstantString,系统进行维护,retain和release不起作用(程序中内容相同的常量字符串只有一个)
  • __NSCFString与其他oc对象一样维护retainCount
  • __NSTaggedPointerString,retain/release不起作用
NSString *a = @"a";
NSString *c = [a copy];
NSLog(@"%p %p", a,c);//输出两个相同的地址,并没有真正的复制

example

__NSCFConstantString

@""格式的字符串

    NSString *str1 = @"rainySue";//__NSCFConstantString
NSLog(@"str1:%d",[str1 retainCount]);// -1

stringWithString+__NSCFConstantString

 NSString *str3 = [NSString stringWithString:@"str3"];//__NSCFConstantString
NSLog(@"str3:%d",[str3 retainCount]); // -1

__NSTaggedPointerString

case1

NSString *str2 = [NSString stringWithFormat:@"%s", "str2"];//__NSTaggedPointerString
NSLog(@"str2:%d",[str2 retainCount]); // -1

case2

 NSString *a = @"a";
NSString *b = [[a mutableCopy] copy];//__NSTaggedPointerString
NSLog(@"b:%d",[b retainCount]); // -1

__NSCFString

通过stringWithFormat构造

NSString *str2_2 = [NSString stringWithFormat:@"%s,%d", "str2_2",22];//__NSCFString
NSLog(@"str2_2:%d",[str2_2 retainCount]); //1

stringWithString + stringWithFormat

NSString *str4_2 = [NSString stringWithString:[NSString stringWithFormat:@"hahah"]];//__NSCFString
NSLog(@"str4_2:%d",[str4_2 retainCount]); // 1 NSString *str4_1_1 = [NSString stringWithString:[NSString stringWithFormat:@"%s", "str2"]];
NSLog(@"str4_1_1:%d",[str4_1_1 retainCount]); //1 NSString *str4 = [NSString stringWithString:[NSString stringWithFormat:@"%s,%d", "str4",22]];//__NSCFString
  NSLog(@"str4:%d",[str4 retainCount]); // 1

stringWithString+__NSTaggedPointerString对象

NSString *str2 = [NSString stringWithFormat:@"%s", "str2"];//__NSTaggedPointerString
NSString *str4_1_1 = [NSString stringWithString:[NSString stringWithFormat:@"%s", "str2"]];
NSLog(@"str4_1_1:%d",[str4_1_1 retainCount]); //1

stringWithString+__NSCFString对象

NSString *str2_2 = [NSString stringWithFormat:@"%s,%d", "str2_2",22];//__NSCFString
SString *str4_3 = [NSString stringWithString:str2_2];
NSLog(@"str4_3:%d",[str4_3 retainCount]); //2

NSMutableString对象

NSMutableString* str5 = [NSMutableString stringWithString:@"str5"];//__NSCFString
NSLog(@"str5:%d",[str5 retainCount]); //1

总结

  • retainCount的不同本质上是因为NSString类簇返回的子类的不同,__NSCFConstantString 和__NSTaggedPointerString初始值为-1,__NSCFString为1
  • 亦可通过方法来区分得到的字符串的类型

    • @”“格式得到的为常量字符串
    • stringWithFormat得到的可能为__NSCFConstantString或者__NSTaggedPointerString
    • stringWithString

    1. stringWithString+__NSCFConstantString得到__NSCFConstantString
    2. stringWithString+stringWithFormat得到__NSCFString,初始计数值为1
    3. stringWithString+__NSTaggedPointerString对象得到__NSCFString,初始计数值为1
    4. stringWithString+__NSCFString对象得到__NSCFString,初始计数值为2

PS:
当开成程序中viewDidLoad里的str指向__NSCFString时,在viewWillAppear和viewDidAppear中就能看到预期的NULL了。

NSString与奇怪的retainCount的更多相关文章

  1. IOS开发之关于NSString和NSMutableString的retainCount

    1. 字符串常量 NSString *s = @"test"; NSLog(@"s:%lx",[s retainCount]); //fffffffffffff ...

  2. iOS中的retainCount

    我们都知道iOS中采用引用计数的技术来管理内存,当一个对象没有任何一个地方引用的时候会自动释放,此时的retainCount为0,而且提供了一个-(NSInteger)retainCount的方法来获 ...

  3. iOS开发系列—Objective-C之Foundation框架

    概述 我们前面的章节中就一直新建Cocoa Class,那么Cocoa到底是什么,它和我们前面以及后面要讲的内容到底有什么关系呢?Objective-C开发中经常用到NSObject,那么这个对象到底 ...

  4. iOS-几大框架的介绍

    1.Objective-C之Foundation框架 概述 我们前面的章节中就一直新建Cocoa Class,那么Cocoa到底是什么,它和我们前面以及后面要讲的内容到底有什么关系呢?Objectiv ...

  5. iOS-Objective-C基础

    一.Foundation框架 概述 我们前面的章节中就一直新建Cocoa Class,那么Cocoa到底是什么,它和我们前面以及后面要讲的内容到底有什么关系呢?Objective-C开发中经常用到NS ...

  6. [OC Foundation框架 - 17] copy语法

    一个对象使用copy或mutableCopy方法可以创建对象的副本 1.copy 需要实现NSCopying协议 创建出来的是不可变副本,如NSString, NSArray, NSDictionar ...

  7. 关于NSString的retainCount的各种结果原因

    转载:http://blog.csdn.net/onlyou930/article/details/6932529 http://www.cnblogs.com/celestial/archive/2 ...

  8. NSString,NSArray,NSNumber等类的继承问题

    问题引入,我想给NSString类扩展一些新的方法.在Objective-C中可以有两种方法,一是继承,二是类别.本文先不讨论类别,我们用继承的方法试一下: @interface StringEx : ...

  9. 引用计数(retainCount)

    ClassA.h: #import <Foundation/Foundation.h> @interface ClassA:NSObject { NSString *name; } -(v ...

随机推荐

  1. 利用chrome调试JavaScript代码

    看见网上很多人问怎么用chrome调试JavaScript代码,我也对这个问题抱着疑问,但是没有找到一篇能用的中文文章(可能我的google有问题),也不知道怎么点出一篇E文的,感觉作者写得不错,所以 ...

  2. 走进异步世界-犯傻也值得分享:ConfigureAwait(false)使用经验分享

    在上周解决“博客程序异步化改造之后遭遇的性能问题”的过程中,我们干了一件自以为很有成就感的事——在表现层(MVC与WebForms)将所有使用await的地方都加上了ConfigureAwait(fa ...

  3. 基于吉日嘎底层架构的通用权限管理Web端UI更新:参考DTcms后台界面

    经一周的研究学习,看了国内的H+.HUI等,国外的PaperDashboardPro.Make.Metronic BootStrap等,最终选定用一个轻量的,适合中国人的,来自DTcms的后台管理UI ...

  4. 清除svn账户账号密码

    1. 2. 3. 4. 5.再次访问时,会弹出要求输入用户名和密码:只是清除记住的用户名和密码.

  5. mybaits 框架运用

    支持普通 SQL 查询,存储过程和高级映射的ORM持久层框架.以一 个 SqlSessionFactory 对象的实例为核心. 从 XML 中构建 SqlSessionFactory configur ...

  6. 点我吧工作总结(技术篇) zookeeper

    我思故我在,提问启迪思考! 1.什么是zookeeper? 2.zookeeper与dubbo.springMVC之间的协同工作? http://doc.okbase.net/congcong68/a ...

  7. Verilog学习笔记认识提升篇(一)...............时序的基本概念(待补充)

    建立和保持时间: 建立时间(Tsu)是指在时钟上升沿到来之前数据必须保持稳定的时间,保持时间(Th)是指在时钟上升沿到来以后数据必须保持稳定的时间.一个数据需要在时钟的上升沿被锁存,那么这个数据就必须 ...

  8. Selenium学习笔记之外部化相关测试数据---xml

    我们也可以用xml来定义一个信息更为丰富的UIMap.xml文件,比如,额外还添加控件所属的页,控件的类型,然后解析构建一个XMLParser类来读取相应的值. <?xml version=&q ...

  9. JSESSIONID与SESSION

    用spring security的时候遇到了一个很诡异的问题: 已经登录的用户,而且没有标记remember-me,在重启服务器之后还会显示已经登录状态 这就严重啦,这样子如果要在session中储存 ...

  10. 20款时尚的 WordPress 博客主题【免费下载】

    在这篇文章中,我们收集了20款时尚的 WordPress 博客模板.WordPress 作为最流行的博客系统,插件众多,易于扩充功能.安装和使用都非常方便,而且有许多第三方开发的免费模板,安装方式简单 ...