在viewDidLoad中的MyViewController中,我只有一个调用:
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
self.isNeedToExecute = YES;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(20 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self doSomeSimpleThings];
});
}
-(void)doSomeSimpleThings {
if (!self.isNeedToExecute) {
return;
}
// do some simple actions
}
- (void)dealloc {
self.isNeedToExecute = NO;
}
之后在代码中我弹出了这个视图控制器,所以没有dispatch_after
,dealloc
肯定会被执行。
问题:
1)在这种情况下是否会调用dealloc方法(当我们有dispatch_after
时,应该在20秒内执行)?
2)此方法[self doSomeSimpleThings];
将在dealloc
之后执行吗?
修改
在发布这个问题之前我试过了,并且没有调用dealloc并认为这很奇怪,这就是我在这里提出这个问题的原因。
答案 0 :(得分:2)
您当前的代码会创建一个保留周期,因为您在块中引用了self
。您可以使用对self
的弱引用来打破周期。这样您也不需要isNeedToExecute
标志:
__weak id blockSelf = self;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(20 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[blockSelf doSomeSimpleThings];
});
取消分配视图控制器blockSelf
后,nil
将无法执行doSomeSimpleThings
。
答案 1 :(得分:1)
在没有对该对象的强引用之后将调用1)在这种情况下会调用dealloc方法(当我们有 dispatch_after,应该在20秒内执行)?
dealloc
。该块具有对该对象的强引用。 dispatch_after
保持阻止直到它运行。因此,在块运行20秒后,将不再有强引用,并且可以释放对象(dealloc
调用)。
2)将此方法[self doSomeSimpleThings];之后执行 的dealloc?
这是倒退的。实际上,当调用dealloc
时,块(包含[self doSomeSimpleThings]
)运行时确定。所以答案是否定的,根据定义,因为dealloc
无法运行,直到在这种情况下无法再运行[self doSomeSimpleThings]
。
答案 2 :(得分:0)
检查 dispatch_after 方法的定义。参数定义为
queue: - 提交块的队列。系统保留队列,直到块运行完成。此参数不能为NULL。
阻止: - < ......>此函数代表调用者执行Block_copy和Block_release。
所以基本上你的控制器对象将被这个队列保留,即使你已经设置它并且方法 doSomeSimpleThings 将被调用然后 dealloc 。