解除模块的模态视图时,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一个更好的地方来调用它可能并不容易。