1. 引子
在面试过程中曾见过这样一道笔试题,选择你认为对的答案
A.所有对象的dealloc方法会在主线程调用
B.一个对象的dealloc方法会在分配该对象的线程被调用
C.一个对象的dealloc方法会在该对象的引用计数变为0的线程被调用
D.手动调用的当前线程中
当时对此题没有明确的答案,回去便开始查阅资料寻找答案。
2.dealloc
对象在经历其生命周期后,最终会为系统所回收,这时就会调用dealloc方法了。在每个对象的生命周期内,此方法仅执行一次,也就是当保留计数降为0的时候。然而具体何时执行,则无法保证。可以简单的理解为:“你绝不应该自己调用dealloc方法,runtime机制会在适当的时候调用他。”这样D答案可以排除。
在看A答案和B答案,我们可以假设如果对象实在主线程中创建在其他线程中被移除,该对象的dealloc应该在主线程中被调用吗?有了这样的假设就应该去小心的验证了,下面给出一段简单的代码。
#import "ViewController.h"
@interface ClassA : NSObject
@end
@implementation ClassA
- (void)dealloc
{
NSLog(@"dealloc is excuted in thread : %@, object : %@", [NSThread currentThread], self);
}
@end
@interface ViewController ()
@property (nonatomic, strong) NSMutableArray *array;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
_array = [NSMutableArray array];
ClassA *objectA = [[ClassA alloc] init];
NSLog(@"Thread: %@, object : %@", [NSThread currentThread],objectA);
[_array addObject:objectA];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[[NSThread currentThread] setName:@"DISPATCH_QUEUE_Thread_Custom"];
[_array removeAllObjects];
});
}
@end
运行得到的输出为
2015-10-07 12:17:46.753 测试[1741:53054] Thread: <NSThread: 0x7ff223411940>{number = 1, name = main}, object : <ClassA: 0x7ff223546510>
2015-10-07 12:17:46.754 测试[1741:53110] dealloc is excuted in thread : <NSThread: 0x7ff223708ec0>{number = 2, name = DISPATCH_QUEUE_Thread_Custom}, object : <ClassA: 0x7ff223546510>
3.结论
可见, objectA
的分配是在主线程, 然后用一个数组来强引用到该对象, 并在一个dispatch_queue
里清空数组,以达到释放 objectA
的目的,输出的结果表明答案应该选
C: 一个对象的dealloc方法会在该对象的引用计数变为0的线程被调用
.