【问题标题】:How do you reload UIViewController's view from a XIB after a memory warning blows it away?在内存警告将它吹走后,如何从 XIB 重新加载 UIViewController 的视图?
【发布时间】:2012-03-18 14:54:11
【问题描述】:

我有一个用 XIB 初始化的 iPhone 视图控制器。

如果出现内存警告时视图控制器的视图不可见,则它将其视图设置为 nil(释放它)。但是当一个重叠的视图被解除并且被清除的视图再次变得可见时,Cocoa 不会从 XIB 重新加载它;它只是创建一个空白。这会留下一个空白屏幕和一个损坏的应用程序。

UIViewController 的 loadView 方法的 Apple 文档说:“如果视图控制器具有关联的 nib 文件,则此方法会从 nib 文件加载视图。如果视图控制器具有关联的 nib 文件,则nibName 属性返回一个非零值。”所以我重写 loadView 只是为了在初始化控制器后检查 nibName ,并且 nibName 是正确的。因此对 loadView 的后续调用应该从 XIB 重新加载。我验证了在内存警告之后再次调用了 loadView

更新:通过更多的测试和记录,我确定在第二次 viewDidLoad 调用之后,视图的 IBOutlets 不为零。由于我在 viewDidUnload 中将它们设置为 nil,因此我得出结论认为视图确实是从 XIB 重新加载的。那么为什么会显示为全白屏呢?

感谢您的任何见解。

这里是 viewDidLoad

- (void)viewDidLoad
{
    [super viewDidLoad];

    _photoViewController = [[EGOSimplePhotoViewController alloc] initWithPhotoSource:_photoSource
                                                                      scrollView:bigImageScrollView
                                                                     enclosingView:photoSquare];
    _photoViewController.delegate = self;

    if(_progressHUD == nil)
    {
        if(self.navigationController.view != nil)
        {
            _progressHUD = [[MBProgressHUD alloc] initWithView:self.navigationController.view];
        }
        else
        {
            _progressHUD = [[MBProgressHUD alloc] initWithView:self.view];
        }
    }

    // Add HUD to screen.
    if(self.navigationController.view != nil)
    {
        [self.navigationController.view addSubview:_progressHUD];
    }
    else
    {
        [self.view addSubview:_progressHUD];
    }

    [_progressHUD release];

    _progressHUD.labelText = @"Loading...";
    [_progressHUD show:YES];
}

以及viewDidUnload

- (void)viewDidUnload
{
    [_photoViewController release];
    [super viewDidUnload];
}

【问题讨论】:

  • 你实现viewDidUnload了吗?
  • 是的。问题是如何重新加载。
  • 如果操作正确,视图会自动重新加载。当控制器即将出现时,它检测到它的视图已被卸载,并发送给自己loadView。请向我们展示loadViewviewDidLoadviewDidUnload 中的代码。
  • 您是否尝试将[super viewDidUnload] 放入您的viewDidUnload 中?您是否覆盖了loadView?如果系统之前曾向您发送过viewDidUnload,则系统绝对应该向您发送loadView(然后是viewDidLoad)。
  • 这个问题开始时我什至没有 viewDidUnload,所以这不是问题(虽然很好)。系统正在向我发送 loadView。它只是第二次没有从 XIB 加载。

标签: iphone ios memory-management uiviewcontroller xib


【解决方案1】:

内存警告后的 viewControllers 视图加载机制应该对开发人员是透明的。您不必做任何事情来重新创建视图。

对于使用 nib 加载的 VC,系统将重新创建视图并调用 viewDidLoad。 对于以编程方式加载的 VC,将再次调用 loadView。

整个循环重复直到 viewDidAppear: 你再次看到视图。

用例:

UITabBarController(假设有 2 个标签)

标签 0 上的用户 >> 转到标签 1 >> 触发内存警告 >> UITabbarController 上的所有活动 VC 都会收到内存警告 >> UITabBarController 将卸载 Tab0 的视图 >> Tab0 收到 viewDidUnload:

当用户切换回 Tab 0 时,它的视图将按照我所说的从 loadView 或 viewDidLoad 开始从头开始创建。

如果您没有收到这些事件,那么您的 viewController 层次结构就会混乱。也许您只是将一些 VC 视图作为子视图添加到某些东西,或者您的 VC 没有直接或通过某些容器控制器(UINavigation、UITabBarController 等)连接到窗口,或者您尝试将自己的 containerController 卷起来并搞砸了。

尝试了解从 loadView 到 viewDidUnload 和 dealloc 的 UIViewController 生命周期。这很棒。这将有助于编写好的代码和设计您的应用程序。

【讨论】:

  • 谢谢。我已经阅读了文档,并且我没有滚动我自己的控制器层次结构。这是一个非常简单的场景:视图控制器调用照片选择器,这通常会产生内存警告。 When the picker's dismissed, the underlying controller's view has been released and is recreated as a white screen.我覆盖了控制器的 loadView 方法并验证了当重叠视图被解除时它确实被调用了。它只是没有重新加载 XIB(是的,它是用一个初始化的)。
  • @Oscar 你找到解决方案了吗?
  • @Adriana:如果您的视图是由 XIB 创建的,您可以使用 nibname 方法重新加载您的视图,但如果它是在没有 Xib 的情况下创建的,那么只需在 -loadView 方法中提供您的视图创建代码并重新创建你看,任何帮助帮助ping我!!!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-29
  • 2012-03-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多