zoukankan      html  css  js  c++  java
  • NSString与奇怪的retainCount

    话题从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了。

  • 相关阅读:
    Windows的本地时间(LocalTime)、系统时间(SystemTime)、格林威治时间(UTCTime)、文件时间(FileTime)之间的转换
    VS2008驱动开发环境配置
    delete和delete[]的区别
    手动加载NT式驱动(非工具)修改注册表实现
    结构体的内存空间分配原理
    NT式驱动的卸载
    NT式驱动的安装
    struct tm>time() localtime() gmtime()
    64位驱动数字签名
    SQL Server 数据库错误修改
  • 原文地址:https://www.cnblogs.com/rainySue/p/NSString-yu-qi-guai-deretainCount.html
Copyright © 2011-2022 走看看