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

文章开头有个小例子

  1. __weak id reference = nil;
  2. - (void)viewDidLoad {
  3. [super viewDidLoad];
  4. NSString *str = [NSString stringWithFormat:@"sunnyxx"];
  5. // str是一个autorelease对象,设置一个weak的引用来观察它
  6. reference = str;
  7. }
  8. - (void)viewWillAppear:(BOOL)animated {
  9. [super viewWillAppear:animated];
  10. NSLog(@"%@", reference); // Console: sunnyxx
  11. }
  12. - (void)viewDidAppear:(BOOL)animated {
  13. [super viewDidAppear:animated];
  14. NSLog(@"%@", reference); // Console: (null)
  15. }

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

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

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

example

__NSCFConstantString

@""格式的字符串

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

stringWithString+__NSCFConstantString

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

__NSTaggedPointerString

case1

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

case2

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

__NSCFString

通过stringWithFormat构造

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

stringWithString + stringWithFormat

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

stringWithString+__NSTaggedPointerString对象

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

stringWithString+__NSCFString对象

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

NSMutableString对象

  1. NSMutableString* str5 = [NSMutableString stringWithString:@"str5"];//__NSCFString
  2. 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. 从C#到Objective-C,循序渐进学习苹果开发(2)--Objective-C和C#的差异

    本随笔系列主要介绍从一个Windows平台从事C#开发到Mac平台开发苹果开发的一系列感想和体验历程,本系列文章是在起步阶段逐步积累的,希望带给大家更好,更真实的转换历程体验. 在上篇<从C#到 ...

  2. asp.net获取站点根目录下子目录的名称

    使用Visual Studio建立一个.aspx文件(Web Forms),例如hovertree.aspx,在页面上加入一个ListBox代码如下: <asp:ListBox runat=&q ...

  3. [DBW]格式化时间

    Date.prototype.format = function(format) { //author: meizz let o = { , //月份 "d+": this.get ...

  4. [前端]使用JQuery UI Layout Plug-in布局 - wolfy

    引言 使用JQuery UI Layout Plug-in布局框架实现快速布局,用起来还是挺方便的,稍微研究了一下,就能上手,关于该布局框架的材料,网上也挺多的.在项目中也使用到了,不过那是前端的工作 ...

  5. ASP.NET入门教程:事件句柄

    事件句柄(event handler)是一种针对给定事件来执行代码的子例程. ASP.NET - 事件句柄 请看下面的代码: <% lbl1.Text="The date and ti ...

  6. Oracle 数据库基础学习 (六) 子查询

    子查询在一个select中出现多个嵌套查询语句 1.在where子句中使用子查询(一般返回"单行单列" "单行多列" "多行单列"(可以提供 ...

  7. CentOS6.5下安装PostgreSQL

    一.配置 YUM 仓库 修改原始的 yum 仓库配置: vim /etc/yum.repos.d/CentOS-Base.repo 在[base]和[updates] 节(section)部分的尾部插 ...

  8. [小北De编程手记] : Lesson 03 玩转 xUnit.Net 之 Fixture(上)

    在使用xUnit.Net Framework构建单元测试或自动化测试项目的时候,无论是针对一些比较耗费资源的对象亦或是为了支持Test case预设数据的能力,我们都需要有一些初始化或是清理相关的动作 ...

  9. Criteria查询初学者的采纳点哦

    一.Hibernate提供了5种检索对象的方式 1.导航对象图检索方式:根据已经加载的对象导航到其他对象    from  Emp e group by e.dept.deptName 2.OID检索 ...

  10. spring 3.x变通实现@Conditional注解的功能

    在某些情况下,我们要根据当前的系统配置决定是否初始化一个bean,也就是条件性加载,比如本地缓存或者分布式缓存,亦或是采用http实现或者socket实现.在spring 4.x中,可以使用新增的@C ...