我有一个订阅其他地方广播的通知的视图控制器。这是一个大型对象图的一部分,当孩子被释放时,需要进行一些清理。但是在其中一个孩子(ARC环境)中从未调用过dealloc,这(如果我理解的话)意味着某处仍然保留了某些东西,因此即使VC被解雇,ARC也永远不会dealloc。我已经将有问题的代码追溯到以下两行。第一个版本导致 VC 和孩子永远不会被完全释放。在第二个版本中,一切正常,当这个 VC 被解散时,一切都得到了释放。
我的问题是为什么?使用 ARC,我无法理解为什么这个额外的 NSArray 不能正确发布。
希望这是足够的代码。有需要可以多发。
这是导致 VC(和孩子等)永远不会被完全释放的版本:
// Subscribe to notifications that the number of trackables has changed
[[NSNotificationCenter defaultCenter] addObserverForName:kUpdatedNumberofTrackables object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
if ([note.object isKindOfClass:[NSArray class]]) {
NSArray *activeTrackableNames = note.object; // <-- offending line
[self trackableUpdate:activeTrackableNames]; // <-- offending line
} else {
NSLog(@"Observer error. Object is not NSArray");
}
}];
但是当我按照以下方式执行此操作时,当视图被卸载时,一切都会正确释放,因此在子 VC 上调用了 dealloc:
// Subscribe to notifications that the number of trackables has changed
[[NSNotificationCenter defaultCenter] addObserverForName:kUpdatedNumberofTrackables object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
if ([note.object isKindOfClass:[NSArray class]]) {
[self trackableUpdate:note.object]; // <-- seems to work
} else {
NSLog(@"Observer error. Object is not NSArray");
}
}];
此 VC 中可能(?)发挥作用的其他一些相关方法:
- (void)viewDidDisappear:(BOOL)animated {
[super viewDidDisappear:animated];
self.trackablesVisible_private = nil;
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
#pragma mark - Target Handling
-(void)trackableUpdate:(NSArray *)trackablesArray {
NSLog(@"Trackable Changed");
if (([trackablesArray count] > 0) && [self.delegate respondsToSelector:@selector(foundValidTargets:)]) {
[delegate foundValidTargets:trackablesArray];
}
self.trackablesVisible_private = trackablesArray;
}
我不明白这里发生了什么。有人可以启发我吗?
谢谢!
编辑:
因此,正如回复中所述,部分问题是由于未能self
在块中使用弱项而导致的保留周期,但显然这里还有另一个问题,因为我正在使用通知中心。解决方案在这里描述:Dealloc Not Running When Dismissing Modal View from Block
我的最终工作代码如下:
在@interface
__weak id observer;
在loadView
__weak ThisViewController *blockSelf = self; // Avoids retain cycle
observer = [[NSNotificationCenter defaultCenter] addObserverForName:kUpdatedNumberofTrackables object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *note) {
if ([note.object isKindOfClass:[NSArray class]]) {
ThisViewController *strongSelf = blockSelf; // Avoids retain cycle
NSArray *activeTrackableNames = note.object;
[strongSelf trackableUpdate:activeTrackableNames];
} else {
NSLog(@"Observer error. Object is not NSArray");
}
}];
而在viewWillDisappear
[[NSNotificationCenter defaultCenter] removeObserver:observer];
我还不完全明白为什么你必须保存返回的观察者对象,而不是仅仅删除self
,但这有效。