理解Autorelease从NSString开始

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。

理解Autorelease从NSString开始_第1张图片
屏幕快照 2018-05-10 上午11.32.24.png

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

理解Autorelease从NSString开始_第2张图片
屏幕快照 2018-05-10 上午11.33.07.png

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

另外

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

Autorelease原理

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

你可能感兴趣的:(理解Autorelease从NSString开始)