话题从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. Hello, Android 快速入门

    Hello, Android Android 开发与 Xamarin 简介 在这两节指南中,我们将 (使用 Xamarin Studio或 Visual Studio)建立我们的第一个 Xamarin ...

  2. [译]WebVR技术方案草案

    注:基于官方的.bs规范专用格式进行了翻译,但结果发现无法编译成html格式,所幸基本兼容.markdown格式. 中文翻译项目地址:https://github.com/web3d/webvr-sp ...

  3. x8086汇编在显存中显示字符串

    题目:在屏幕中间显示绿色,绿底红色,白底蓝色的字符串‘welcome to masm!’ 80X25彩色字符模式显示缓冲区的结构: 在内存地址结构中,B8000H~BFFFFH共32KB的空间,为80 ...

  4. linux非常用但很有用的命令

    查找指定目录下包含指定字符串的所有文件 grep -rl 'abc' / top查看命令的完整启动路径 top 按c top以MB为单位显示内存信息 top -M 查看内存top io趋势 pidst ...

  5. 奇怪的Hibernate——当?遇上%

    今天写了一个模糊查询的SQL语句,发现了点有趣的东东 情景: 平时写模糊查询的时候是"select * from user where username like %?%" 然后就 ...

  6. 那些年,我们一起疯狂的C#

    v\:* {behavior:url(#default#VML);} o\:* {behavior:url(#default#VML);} w\:* {behavior:url(#default#VM ...

  7. Frameless - 用于预览 iOS8 原型的浏览器

    Frameless 是一个用于在 iOS8 中预览产品原型的浏览器.可以可以帮助那些需要一个简单的方法来预览 iOS 设备上的原型设计和开发效果.没有状态栏,通过手势控制浏览器的历史以及键盘的显示. ...

  8. 类似 Dribbble 下载按钮的 SVG 弹性动画进度条

    Codrops 发布了一个如何创建一个基于弹性效果的 SVG 加载进度条教程,基于 SVG 和 TweenMax 实现.按钮开始的时候是一个带有箭头的图标,一旦它被点击,动画成一个有趣的小金属丝和一个 ...

  9. 使用 WordPress 主题制作的20个精美网页

    WordPress 是一款个人博客系统,并逐步演化成一款内容管理系统软件,它是使用 PHP 语言和 MySQL 数据库开发的.用户可以在支持 PHP 和 MySQL 数据库的服务器上使用自己的博客.这 ...

  10. js取url参数

    function GetQueryString(name) { var reg = new RegExp("(^|&)"+ name +"=([^&]*) ...