你能缓存 UIViewControllers 吗?

Posted

技术标签:

【中文标题】你能缓存 UIViewControllers 吗?【英文标题】:Can you cache UIViewControllers? 【发布时间】:2011-01-12 16:42:38 【问题描述】:

我有一个带有 8 个 UIViewControllers 的应用程序,通过从左/右/上/下导航呈现。它们在应用程序启动时创建并保存在 NSArray 中。任何时候都只会将其中的 1 个添加到视图树 (addSubview:) 中 - 其余的只是放在缓存中,直到需要它们为止。

现在我遇到的问题是旋转到横向时。只有当前可见的视图将 bounds.size 更改为 Landscape。当导航到下一个视图时,该视图仍然认为它是纵向的(但包含的视图都将在横向中查看)。

顺便说一下,应用程序的视图层次结构如下:UIWindow -> Main UIViewController -> 8 个缓存的 UIViewController 中的 1 个。

例如: * 改变方向: - 主 UIViewController.view.bounds.size = 480x300 (OK) - 缓存的 UIViewControllers view.bounds.size 之一 = 480x300 (OK) * 转到下一个视图: - 主 UIViewController.view.bounds.size = 480x300 (OK), - 另一个缓存的 UIViewControllers view.bounds.size = 320x460 (??)

不知道发生了什么。我是否必须以某种方式告诉缓存的 UIViewControllers 方向/大小发生了变化或其他什么?

非常感谢

【问题讨论】:

为什么不使用 UINavigationController 来推送/弹出和替换当前视图? 即使使用 UINavigationController,我仍然遇到问题。还有其他一些事情会阻止视图调整大小。 【参考方案1】:

是的,你可以。最佳情况下,您应该在每个视图控制器离开屏幕时清除它管理的视图。

只需将nil 分配给要替换的视图控制器的view 属性。这将释放视图使用的所有不可见的资源。作为一个额外的好处,每当您决定再次将特定的视图控制器置于前面时,该视图就会使用适当的框架重新创建。

我还假设您正在实现的是UIViewController 的子类,它充当其他视图控制器的容器。就像 UITabController 的兄弟姐妹,名为 CWGridController 或类似名称。不,父视图控制器(您的子类)有责任根据需要调整其子视图控制器视图的框架。

创建容器视图控制器不是一项小任务,Apple 对它的支持并不完整。您必须做一些事情,包括但不限于:

将所有方向更改调用转发到所有子视图控制器。 根据需要正确调用子视图控制器上的所有出现/消失。

让它发挥作用的最后一部分是打破一些规则。除非他们知道他们的父视图控制器,否则视图控制器的工作非常糟糕,布局将是错误的并且模态视图控制器的行为很奇怪。不幸的是,parentViewController 是只读的,或者你会这么想。使用 KVC 设置它可以解决大多数问题,并且当您提交到 App Store 时,Apple 似乎并不反对:

[childViewController setValue:self forKey:@"parentViewController"];

【讨论】:

我尝试在移动到下一个时设置 nextController.view = nil 但没有帮助。是的 UIViewController 一次只充当 1 个 UIViewController 的容器。另一个 UIViewController 在一个数组中。当用户导航下一个时,当前 UIViewController 的视图从 superview 中移除并添加下一个。问题可能是我正在使用 UIView 制作动画,而应该使用 UIViewController 制作过渡动画。 您的控制器充当容器,就像UITabBarController 是许多视图控制器的容器一样。两者一次只显示其中一个的视图。从概念上讲,你在做同样的事情,只是呈现方式不同。为了使其按预期工作,您必须履行作为容器视图控制器的义务。例如,您必须在适当的时间在包含的视图控制器上调用viewDidAppear:viewDidDisappear: 等。否则包含的视图控制器无法知道它们的当前状态。 感谢您为我指明正确的方向。我认为我的整个方法都是错误的。我必须重新考虑如何在我的应用程序中管理视图控制器。我将按需创建它们(而不是缓存它们)并将昂贵的东西缓存在视图和模型中。将需要一些时间来返工。谢谢。 @vance:很高兴。必须说我钦佩任何愿意根据新信息重新设计的开发人员。【参考方案2】:

在 viewWillAppear 中,您必须检查界面方向并相应地设置框架。

【讨论】:

"- (void)viewDidAppear:(BOOL)animated" 仅在我启动应用程序时触发 - 对于第一个视图。这可能与使用 [UIView beginAnimations...] 和 [current.view.superview addSubview:next.view] 转换到下一个可能的视图的方式有关。 您可以尝试隐藏视图,而不是添加和删除视图。 view.hidden = YES;这样,视图仍将正确地自动旋转。

以上是关于你能缓存 UIViewControllers 吗?的主要内容,如果未能解决你的问题,请参考以下文章

使用 JavaScript Axios/Fetch。你能禁用浏览器缓存吗?

你能帮我理解 ARM Cortex-A9 上的缓存行为吗?

将 UIViewControllers 放在其他 UIViewControllers 中是不好的做法吗?

当我的容器 UIViewController 被解除分配或卸载时,我必须清理我的子 UIViewControllers 吗?

iOs 中所有 uiviewcontrollers 中的操作栏

UITabBar 控制器选项卡导航到不同的 UIViewControllers