美文网首页
理解Autorelease从NSString开始

理解Autorelease从NSString开始

作者: 老薛有只猫 | 来源:发表于2018-05-10 12:06 被阅读59次

    2018年5月10日

    前言

    首先声明本文涉及到的内容并非本人原创,只是笔者在工作中遇到相关问题,通过查阅前人的成果,自己做的一些总结,初衷是加深印象,也方便自己以后查阅,如果能对读者有所帮助,那是鄙人的荣幸。

    从NSString说起

    #define Log(_var) ({ NSString *name = @#_var; NSLog(@"%@: %@ -> %p : %@", name, [_var class], _var, _var);})
    __weak NSString *weak_string = nil;
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        // 场景:1
        NSString *string1 = @"常量";
        weak_string = string1;
        
        /*
        // 场景:2
        NSString *string2 = [[NSString alloc] initWithFormat:@"实例方法"];
        weak_string = string2;
        
        */
        
        /*
        // 场景:3
        NSString *string3 = [NSString stringWithFormat:@"类方法"];
        weak_string = string3;
         */
    }
    
    - (void)viewWillAppear:(BOOL)animated {
        [super viewWillAppear:animated];
        
        NSLog(@"%s", __func__);
        Log(weak_string);
    }
    
    - (void)viewDidAppear:(BOOL)animated {
        [super viewDidAppear:animated];
        
        NSLog(@"%s", __func__);
        Log(weak_string);
    }
    

    输出

    -[ViewController viewWillAppear:]
    weak_string: __NSCFConstantString -> 0x10cb408e0 : 常量
    -[ViewController viewDidAppear:]
    weak_string: __NSCFConstantString -> 0x10cb408e0 : 常量
    
    -[ViewController viewWillAppear:]
    weak_string: (null) -> 0x0 : (null)
    -[ViewController viewDidAppear:]
    weak_string: (null) -> 0x0 : (null)
    
    -[ViewController viewWillAppear:]
    weak_string: __NSCFString -> 0x60c00002ece0 : 类方法
    -[ViewController viewDidAppear:]
    weak_string: (null) -> 0x0 : (null)
    

    场景:1

    第一种情况没的说,string1的class是__NSCFConstantString,编译期创建,放在常量区,程序销毁的时候才被释放。

    场景:2

    第二种情况也很好理解,通过alloc在堆上分配内存的局部变量,作用域结束被自动回收,所以在viewWillAppearviewDidAppear的时候string2已不复存在。

    场景:3

    下面着重说一下通过类方法stringWithFormat创建的对象。
    为了更直观,我们拿场景2做对比,通过设置观察点发现alloc创建的对象在viewDidLoad作用域结束的时候就被回收了,而此时AutoreleasePool并没有被pop。

    屏幕快照 2018-05-10 上午11.32.24.png

    再观察一下类方法创建的对象,viewWillAppear方法结束的时候执行了 AutoreleasePoolPage::pop(void*)方法。

    屏幕快照 2018-05-10 上午11.33.07.png

    由此我们可以得出结论,通过类方法创建的对象生命周期延长了,直到自动释放池被pop的时候才被销毁。同时也再次证明sunnyxx大神的论断viewDidLoadviewWillAppear是在同一个runloop调用的。

    另外

    无论使用alloc还是类方法创建的对象,当内容是数字、英文字母、字符等,只要字符串的长度小于等于9就会转成NSTaggedPointerString类型。长度大于9或者有中文在就会变成NSCFString类型。NSTaggedPointerString类型也不会释放,其实对于NSTaggedPointerString类型来说,它的内容就在本身的指针里,不存在释放的问题。

    Autorelease原理

    sunnyxx大神的《黑幕背后的Autorelease》写的很清楚了,这里不再赘述,有兴趣的可以去拜读一下,写的相当棒。

    相关文章

      网友评论

          本文标题:理解Autorelease从NSString开始

          本文链接:https://www.haomeiwen.com/subject/urzarftx.html