解除模块的模态视图时,Dealloc不运行

这里有一个奇怪的,dealloc不被称为从块内被解雇。 码:

[[NSNotificationCenter defaultCenter] addObserverForName:@"user.login" object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notif) { [self dismissModalViewControllerAnimated:YES]; }]; 

任何人都知道为什么会这样? 我怎么可以从块内部解雇并同时运行dealloc?

我试过自我执行select器,但这没有任何区别。

谢谢

我把你引用到: 块中引用自我计数

该块将保持self直到该块被释放。 所以要释放self ,你需要删除观察者。

这可能是相关的UIKit不是完全线程安全的? UIKit应该只在主线程上使用…

如果是这样,我会build议使用:

 performSelectorOnMainThread:withObject:waitUntilDone: 

( 参考 )

(1)您的代码错误(不完整)。 当你发出addObserverForName:你必须捕获返回的值; 这是观察者的标志。 你存储这个地方(例如一个实例variables):

 self->observer = [[NSNotificationCenter defaultCenter] addObserverForName:@"woohoo" object:nil queue:nil usingBlock:^(NSNotification *note) { //whatever }]; 

之后,当您离开时,通过调用removeObserver:将该标记作为参数从通知中心删除该观察者标记。 如果你不这样做,你可以稍后崩溃。

 [[NSNotificationCenter defaultCenter] removeObserver:self->observer]; 

(2)但是等等,还有更多! 在ARC下,当这个块被复制时,你会得到一个保留周期。 这是因为存储的观察者令牌包含该块并且本身保留自己。 我会给你三种方式来打破这个保留周期:

(a)将观察者令牌存储为弱引用:

 __weak id observer; 

(b)将观察者标记存储为强引用,但在删除观察者时显式释放(通过剔除):

 [[NSNotificationCenter defaultCenter] removeObserver:self->observer]; self->observer = nil; // crucial 

(c)当你创build块(我假装self是一个FlipsideViewController)时,就像这样做“弱强舞”:

 __weak FlipsideViewController* wself = self; observer = [[NSNotificationCenter defaultCenter] addObserverForName:@"user.login" object:nil queue:nil usingBlock:^(NSNotification *note) { FlipsideViewController* sself = wself; [sself dismissModalViewControllerAnimated:YES]; }]; 

现在,你可能会认为,“弱强舞”是一个极端的方法,正如我的评论者所暗示的那样。 但它有一个巨大的优势:它是这三种解决scheme中唯一允许您在dealloc删除观察者的方法。 使用其他两种解决scheme,直到调用removeObserver: 之后才会调用removeObserver: – find一个更好的地方来调用它可能并不容易。