其他分享
首页 > 其他分享> > iOS笔记 - Autorelease调用时机(对象出了方法就立即销毁?)

iOS笔记 - Autorelease调用时机(对象出了方法就立即销毁?)

作者:互联网

Autorelease调用时机

1 - 我们先看代码

① 示例一:MRC模式

// - Person.m

 1 #import "Person.h"
 2 
 3 @implementation Person
 4 
 5 -(void)dealloc{
 6     
 7     NSLog(@"person dealloc");
 8     [super dealloc];
 9 }
10 
11 @end

// - ViewController.m

 1 #import "ViewController.h"
 2 #import "Person.h"
 3 @implementation ViewController
 4 
 5 - (void)viewDidLoad {
 6     [super viewDidLoad];
 7     
 8     Person *p1 = [[[Person alloc] init] autorelease];
 9     NSLog(@"%s",__func__);
10 }
11 
12 
13 - (void)viewWillAppear:(BOOL)animated{
14     
15     [super viewWillAppear:YES];
16     
17     NSLog(@"%s",__func__);
18 }
19 
20 -(void)viewDidAppear:(BOOL)animated{
21     
22     
23     [super viewDidAppear:YES];
24      NSLog(@"%s",__func__);
25 }
26 
27 @end

日志信息:貌似和我们往常想象不一样(不是 Person对象出了自己的方法后就立即销毁了吗?)

② 示例二:ARC模式中依旧沿用示例一的代码(注意更改 Person的 dealloc方法),viewDidLoad中的 Person去掉 autorelease 

1 - (void)viewDidLoad {
2     [super viewDidLoad];
3     
4     Person *p1 = [[Person alloc] init];
5     NSLog(@"%s",__func__);
6 }

日志信息:这一次和我们平常理解的一样(Person对象出了方法立刻销毁)

2 - ARC中对象出了方法立刻销毁,这是没问题的。问题就出现在 MRC中的 autorelease,因为它是和 Runloop有关联的

① 我们知道 iOS在主线程的 Runloop里注册了两个 observer

- (void)viewDidLoad {
    [super viewDidLoad];
    
    NSLog(@"%@",[NSRunLoop mainRunLoop]);
}

日志信息:只截取 Observers

activities 是 kCFRunLoopBeforeTimers的枚举值

1 typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) {
2     kCFRunLoopEntry = (1UL << 0),
3     kCFRunLoopBeforeTimers = (1UL << 1),   // 2
4     kCFRunLoopBeforeSources = (1UL << 2),  // 4
5     kCFRunLoopBeforeWaiting = (1UL << 5),  // 32
6     kCFRunLoopAfterWaiting = (1UL << 6),   // 64
7     kCFRunLoopExit = (1UL << 7),           // 128
8     kCFRunLoopAllActivities = 0x0FFFFFFFU
9 };

我们看到两个观察者的 activities分别是 0x1 =1、0xa0 = 160 = 128+32,也就是一个监听 kCFRunLoopEntry,一个监听 kCFRunLoopBeforeWaiting和 kCFRunLoopExit

② 结论

第一个 Observer监听了 kCFRunLoopEntry事件,会调用 objc_autoreleasePoolPush()

第二个 Observer监听了 kCFRunLoopBeforeWaiting事件,会调用 objc_autoreleasePoolPop()、objc_autoreleasePoolPush();它还监听了 kCFRunLoopExit事件,会调用 objc_autoreleasePoolPop()

结语

1 - ARC中对象出了方法即被销毁,但对于 autorelease(MRC)它是由 Runloop来控制的,可能会是在某次 Runloop循环休眠之前调用了 release

 

标签:__,销毁,NSLog,void,iOS,Autorelease,Person,viewDidLoad,super
来源: https://www.cnblogs.com/self-epoch/p/16311633.html