切换视图时的 iOS 特定行为

Posted

技术标签:

【中文标题】切换视图时的 iOS 特定行为【英文标题】:iOS specific behavior when switching views 【发布时间】:2012-06-16 18:44:49 【问题描述】:

我看到一个与调用子视图方法相关的奇怪问题,这似乎是特定于 ios 版本的。

我有两个带有父视图控制器的可交换视图,而不是决定显示哪一个。基本上,登录视图会在您登录时换出到帐户视图,并在您注销时换回登录。

代码非常简单。这是您登录时调用的父视图控制器的示例方法:

- (void) showAccountView:(BOOL)animated

    if(self.accountController == nil)
        self.accountController = [[[AccountViewController alloc] initWithNibName:@"AccountViewController" bundle:nil] autorelease];

    [self.loginController viewWillDisappear:animated];
    [self.accountController viewWillAppear:animated];

    [self.loginController.view removeFromSuperview];
    [self.view insertSubview:alertsController.view atIndex:0];

    [self.loginController viewDidDisappear:animated];
    [self.accountController viewDidAppear:animated];

还有一个类似这样的用于显示登录视图。很简单。我遇到的问题是 viewWillAppear、viewDidAppear、viewWillDisappear、viewDidDisappear 方法都在 iOS 4.3 下被调用一次,但在 iOS 5.0 和 5.1 下被调用两次。

例如,在所有 iOS 版本中,子视图的 viewWillAppear 会在父视图直接调用时被调用(当然)。但是,只有 iOS 5.0 和 5.1 会在调用 insertSubview 期间再次调用它。

所以,如果我删除除了对 removeFromSuperview 和 insertSubview 的调用之外的所有内容,那么它看起来像这样:

- (void) showAccountView:(BOOL)animated

    if(self.accountController == nil)
        self.accountController = [[[AccountViewController alloc] initWithNibName:@"AccountViewController" bundle:nil] autorelease];

    [self.loginController.view removeFromSuperview];
    [self.view insertSubview:alertsController.view atIndex:0];

现在在 5.0 和 5.1 下,子视图方法在 insertSubview 期间仅被调用一次。但是,它在 4.3 下会导致问题,因为它们根本不会被调用。

我已经阅读了几篇与确保调用子视图方法相关的帖子,但我还没有看到类似这样的行为是依赖于 iOS 的。

我能想到的唯一方法是在运行时检查 iOS 版本并直接为 iOS 4.3 调用子视图方法,而不是在 5.0 和 5.1 下调用它们。

有什么想法吗?

【问题讨论】:

首先,你不应该打电话给viewWill/Did...其次,你怎么知道他们没有被打电话? 我同意你的观点,我不应该给他们打电话,但显然我这样做了,因为他们在 4.3 中没有被自己调用。我可以告诉他们没有被调用,因为我设置的断点没有被击中。此外,从视图的功能可以明显看出它们没有被调用。实际上,我刚刚发现 this post 讨论了与我在答案中看到的问题类似的问题。他们似乎认为这是 iOS 中的一个错误,并建议使用动态版本检查。 【参考方案1】:

你不应该在另一个视图控制器中拥有一个视图控制器的内容,除非在 iOS 5 中添加了新的父/子视图控制器支持。现在正式支持使用许多新方法(例如 addChildViewController、transitionFromViewController :toViewController:duration:options:animations:completion)

如果您确实尝试在 iOS 4 或更早版本下将一个视图控制器的视图托管在另一个视图控制器中,那么您每一步都在与操作系统作斗争。

【讨论】:

我从一本 iOS 开发书籍中得到了这种技术,并不是说它是正确的。那么,使用 5.0 之前的 iOS 版本实现我正在做的事情的合适方法是什么? @Duncan C 我了解某些 ViewController 存在限制,例如UISplitViewController 必须是根。但是,将 UITableViewController 放在 UISplitViewController 中是很常见的。请您澄清您的观点,或指出支持它的文档?谢谢。 @strips,我的意思是在 iOS 5 之前,您不应该将您的自定义视图控制器的内容之一放入另一个内容中。 Apple 的容器视图控制器(导航控制器、标签栏控制器和 iPad 上的拆分视图控制器)是特殊的,旨在包含其他视图控制器。 iOS 5 内置的父/子视图控制器方案允许您创建自己的具有不同行为的容器视图控制器。我进行了一些挖掘,但在文档中找不到关于 iOS 5 之前的花药中不应有一个视图控制器视图的声明,但我已经看到了。

以上是关于切换视图时的 iOS 特定行为的主要内容,如果未能解决你的问题,请参考以下文章

从 Tab View Controller 切换到滑动手势时的 iOS Xcode 问题

滚动水平集合视图时的随机行为

使用标签栏控制器时的方向问题

布局右侧和底部的视图在移动时的行为与左侧和顶部的视图不同

中心控制器具有滚动视图时的 MMDrawerController 平移手势行为

在 SwiftUI 视图中的 TextField 后面使用多个 SecureField 时的奇怪行为