2

我有一个相对简单的问题,一段时间以来一直在逃避解决方案。我有一个视图控制器和一个关联的 XIB。视图控制器称为FooterViewController. FooterViewController的视图设置为 tableview 的页脚视图。

FooterViewController的视图包括一个用于向用户显示反馈的标签。我希望这个标签一直存在,直到它的值被我的应用程序更改。在正常情况下,确实如此。但是,我刚刚开始使用内存警告进行测试,我发现在卸载视图以响应内存警告后,标签被清除。

到目前为止,这是我为解决问题所做的尝试:在FooterViewController's viewWillUnload方法中,我将标签的文本存储在一个名为的实例变量中statusString

- (void)viewWillUnload
{
    statusString = [statusLabel text];
    testInt = 5;
    NSLog(@"View will unload; status string = %@; testInt = %d", 
            statusString, testInt);

    [super viewWillUnload];
}

请注意,我还将另一个实例变量(声明为NSInteger testInt)设置为 5。

然后,在FooterViewController'sviewDidLoad方法中,我尝试将标签的文本设置为statusString

- (void)viewDidLoad
{
    [super viewDidLoad];

    NSLog(@"Just before setting label, statusString: %@; testInt: %d", 
            statusString, testInt);
    [statusLabel setText:statusString];
    NSLog(@"View did load.");
}

但是,这不起作用。此外,在模拟内存警告后的日志中,我看到:

View will unload; status string = Invalid IP address Error code: 113; testInt = 5

(注意“Invalid IP address Error code: 113”是statusString的正确值)

然后,FooterViewController再次导航到后,我看到:

Just before setting label, statusString: (null); testInt: 0

这向我表明,由于某种原因,FooterViewController当视图再次加载时,实例变量正在重新初始化。最后一点:initWithNibName:bundle:每次必须重新加载视图时都会调用该方法,尽管我希望如此;毕竟,视图必须从 NIB 重新加载。

所以,我的问题是:

  1. 为什么这些实例变量在卸载和重新加载视图的过程中似乎被取消或归零?
  2. 如果我做错了导致这种无效的事情,那是什么?
  3. 如果我没有做错任何事情,这是正常行为,我应该如何处理视图加载之间的维护状态?

谢谢,莱利

4

3 回答 3

0

statusString 看起来像一个弱引用,而不是一个强属性。它不能保留标签的文本,当视图被卸载时,这些文本会随着标签一起被释放。这就是为什么你首先得到一个正确的值(在标签被释放之前),然后是 null (在标签被释放之后,并且弱引用无效)。把你的 statusString 变成一个强大的属性,ARC 魔法就不会再咬你了。

于 2012-06-18T18:10:27.173 回答
0

看起来您需要使用 didRecieveMemoryWarning 而不是 viewDidUnload,因为不能保证在发生内存警告时调用 viewDidUnload。如果崩溃完全退出应用程序,那么您需要使用 coreData 之类的东西将数据写入磁盘。在此处保存您的数据,然后调用 super 以便仍会释放视图。希望有帮助。

于 2012-06-18T19:33:36.397 回答
0

我终于明白发生了什么事。问题是我FooterViewController在其父视图控制器的方法中调用了分配和初始化方法viewDidLoad。当视图被转储并随后重新加载时,我的视图控制器被重新初始化!这破坏了原来的FooterViewController,它保留了我需要的实例变量,并用一个全新的 VC 替换它。

解决方案是转移[[FooterViewController alloc] init]到的父 VC 的init方法FooterViewController,以便每个运行周期只执行一次初始化。

我已经吸取了教训:除非您真的打算这样做,否则不要重新初始化您的视图控制器。 因此,在调用父视图控制器中的初始化程序时要非常小心。

感谢两位答主给我的帮助。

于 2012-06-19T03:01:29.437 回答