我有一个UINavigationController,当用户循环浏览页面时(总是相同的顺序),它会将三个视图推送到它上面 - 我将它们称为views0,1和2,以与导航控制器指示对齐。视图在Storyboard中创建。
当完成视图的进展,并且用户想要返回到开头时,我使用popToRootViewControllerAnimated:YES来响应按钮按下,并且UI适当地返回到view0。但是,如果我再次进行循环,我偶尔会得到“幻影”日志语句以响应应用程序范围的通知,清楚地表明view1(中间视图)从未完全解除分配。我只在xcode 4.2.1中使用ARC而只使用iOS5 +代码,所以ARC应该很好地处理好事情。
我已经看到一些帖子暗示ARC不会释放引用计数未降至0的视图,所以我已经尽力将属性设置为nil完成后,并进行了双重检查当我推到最终视图时什么也没有留下......而且NavigationController之外的任何内容都没有引用view1(我知道)。为僵尸和内存泄漏分析应用程序不会产生任何结果。
如何查看/记录/调试可能仍在引用视图的内容?我怎么能说它没有放入能防止dealloc的内容而被成功解除了?
我的代码(基本上)如下:
view0在故事板中使用“推送”segue推送到view1。
查看1:
- (void)viewDidLoad
{
[super viewDidLoad];
/* register as observer for some notifications */
/* set properties and format an image or two */
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
/* start some animation here */
}
- (void) receiveNotification {
NSObject *newObject = [[NSObject alloc] init];
[newObject doStuff];
/* Remove notification observers */
}
- (void)objectDelegateMethod:(NSDictionary *) dataReturned {
/* do stuff with dataReturned */
self.propertyName = dataReturned;
[self performSegueWithIdentifier:@"AllDone" sender:self];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([[segue identifier] isEqualToString:@"AllDone"])
{
View2ViewController *destinationView = [segue destinationViewController];
destinationView.propertyMagic = self.propertyName;
[self setPropertyName:nil];
//do same with all other properties
}
视图2:
- (void)viewDidLoad
{
/* display things based on self.propertyMagic */
}
- (IBAction)userStartsOverButton:(id)sender {
[self.navigationController popToRootViewControllerAnimated:YES];
}
鉴于上述(粗略)结构,如果我不删除view1作为通知的观察者,它会继续响应并输出到日志,即使我看不出为什么它没有被解除分类。即使我删除观察者,内存使用量也会继续增加,因为我在应用程序运行中循环并最终崩溃(仪器中没有检测到泄漏)。
我如何解决这个问题?
答案 0 :(得分:1)
如果你有泄漏和僵尸,那么......你可能没有任何泄漏或过度释放。
要在ARC下“看到”dealloc,您可以在班级中添加空记录dealloc
:
- (void)dealloc { NSLog(@"%s:%d", __func__, __LINE__); }
答案 1 :(得分:0)
您可以检查的一件事是,是否有任何其他Object具有指向view1的(strong)
指针。如果是这样,您可能希望将其更改为(weak)
或仅保留对它的引用。 (查看view0和view1之间以及view1和view2之间可能的保留周期,也许它们彼此保持引用。)
ARC将在对象上释放,如果它不再由任何其他对象拥有。所以你也可以尝试覆盖view0上的-popToRootViewControllerAnimated:
方法并调用类似的东西:
self.view1 = nil;
如果view0是唯一保持对view1的引用的对象,则应释放view1(dealloced)。