IOS基础和进阶开发iOS开发好文iOS开发技术分享

iOS内存管理基础0

2019-01-06  本文已影响2人  王大吉Rock

一个oc对象的引用计数时机

最近冥想一个这样的问题:我们都知道ARC机制是一种简单有效地管理oc对象生命周期的方式,当一个实例被创建的时候,实例的引用计数会变成1,当一个新的指针指向实例的时候,它的引用计数会变成2,当没有指针指向这个实例的时候它的引用计数会变成0,这个时候ARC机制会销毁该实例并回收内存...
那么一个继承于NSObject类的实例,其引用计数是什么时候第一次被+1的呢,是alloc的时候,还是init的时候,还是时候呢?

这是一个非常基础的问题,我们分为下面三种情况分析下

情况1:

其实我们知道新实例被创建后,只要被强引用了,其引用计数必然会+1,那么在一个函数中如果我们只创建了一个实例:

- (void)test {
    [[NSObject alloc] init];
}

此实例的引用计数是怎么样的呢?
我们知道alloc的时候实例的内存被分配,init的时候实例内部的属性等会被创建,但是其没有被任何对象或者属性引用,可以认为是没有被指针指向的,所以此时实例的引用计数为0,当执行完test函数后,实例会被销毁。

情况2:

- (void)test {
    NSObject *obj = [[NSObject alloc] init];
    NSLog(@"引用计数:%lu", (unsigned long)[obj retainCount]);
}

那如果是这样,其实例的引用计数会是多少呢?
答案是:引用计数:1,因为实例被创建后,被obj变量的指针所指向了,也就是说objc变量持有了该实例,所以打印的结果会是1。同样的,当执行完test函数后,实例会被销毁。

情况3:

#import "ViewController.h"

@interface ViewController ()

@property(nonatomic, strong) NSObject *obj;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    [self test];
    NSLog(@"引用计数:%lu", (unsigned long)[self.obj retainCount]);
}

- (void)test {
    NSObject *obj = [[NSObject alloc] init];
    NSLog(@"引用计数:%lu", (unsigned long)[obj retainCount]);
    self.obj = obj;
    NSLog(@"引用计数:%lu", (unsigned long)[obj retainCount]);
}
@end

此时两次的log是如何呢?
答案是:引用计数:1引用计数:2引用计数:2[[NSObject alloc] init]实例创建后被objself. obj两个变量的指针指向了...函数结束后,因为ViewController持有self. objself. obj持有着实例,所以其引用计数不会为0

引用计数和方法作用域

在上述情况2中最终[[NSObject alloc] init]实例会被销毁呢?
答案是和函数的作用域有关系的,函数中的局部变量是在中,比如情况2中的obj变量,其本质就是一个指针,在函数结束的时候,系统就会释放这个指针。所以函数结束时,就没有指针指向实例,其引用计数为0,在ARC的环境下就会自动销毁该实例。

如果你想了解iOS的内存存储区域、循环引用&解决循环引用的本质,可以转到iOS内存管理基础1

上一篇下一篇

猜你喜欢

热点阅读