iOS 中的 viewWillAppear:方法的实质与使用方法

作者: IT Sectr 发布日期: 2026-03-05 阅读时间: 8 分钟

viewWillAppear — 是 UIViewController 的一个方法,UIKit 在屏幕对用户可见之前每次都会调用它。根据 Apple Developer Documentation,这个方法接收一个布尔参数 animated,指示转换是否伴随动画。viewWillAppear — 是更新数据和同步屏幕状态的主要位置。

要点

  • viewWillAppear 在每次屏幕出现时被调用,与 viewDidLoad 不同
  • 用于更新数据和从其他屏幕返回后的同步
  • animated 参数指示出现是否伴随动画
  • 在这里配置NavigationBar、TabBar 和其他界面元素
  • 适用于订阅临时通知,仅在屏幕可见时激活

什么是 viewWillAppear

viewWillAppear — 是 UIViewController 的一个方法,UIKit 在将 View 添加到窗口层次结构之前立即调用。此时,View 在经过 Auto Layout 后已有最终尺寸,但对用户尚不可见 — 过渡动画要么尚未开始,要么正在执行。开发者重写此方法以执行每次屏幕显示前应发生的操作。

与只执行一次的 viewDidLoad 不同,viewWillAppear 在屏幕即将出现时每次都被调用:在初始打开时、从子控制器返回时、关闭模态窗口后以及在切换 TabBar 标签时。这使其成为维护界面最新状态的关键方法。

该方法接收 Bool 类型的 animated 参数,如果屏幕出现伴随动画则为 true。此参数便于传递给具有类似参数的 NavigationBar 和 TabBar 方法,以实现一致的行为。

viewWillAppear 何时被调用

时机 viewWillAppear 的调用取决于导航类型,但一般规则不变:该方法在 View 变为可见之前执行。让我们看看主要场景。

在首次打开屏幕时

在调用 viewDidLoad 后,UIKit 开始准备显示:View 被添加到层次结构中,执行 layout 步骤,然后就在过渡动画开始之前调用 viewWillAppear。此时屏幕尚不可见,但所有子视图都有正确的尺寸,可以安全地更新其内容。

从 NavigationController 返回时

当用户按下返回按钮或以编程方式调用 popViewController 时,UIKit 返回到上一个屏幕并调用其 viewWillAppear。这是使用 viewWillAppear 的主要场景 — 在添加元素后更新列表或同步设置。

swift
override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    tableView.reloadData()
    updateBadgeCount()
}

关闭模态窗口时

在关闭以模态方式呈现的控制器后,UIKit 在呈现该控制器的控制器上调用 viewWillAppear。如果您使用委托或闭包来回传数据,此场景需要特别注意 — viewWillAppear 确保屏幕在收到结果后更新。

切换 TabBar 标签时

TabBarController 在每次切换时调用所选标签控制器的 viewWillAppear。如果标签上显示动态数据 — 汇率、通知、用户状态 — viewWillAppear 是更新它们的理想位置。

viewWillAppear 中的实际任务

viewWillAppear 解决了一些在其他方法中无法执行或不是最优的具体任务。让我们看看主要的。

更新表格数据

viewWillAppear 最常见的用途 — 在每次屏幕出现时重新加载UITableView 或 UICollectionView。如果数据在上一个屏幕上可能已更改(添加元素、更改状态),在 viewWillAppear 中调用 reloadData 可确保用户看到最新信息。

swift
override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    viewModel.synchronize()
    tableView.reloadData()
}

配置 NavigationBar 和 TabBar

在 viewWillAppear 中可以方便地配置 NavigationBar 的外观:隐藏或显示、更改颜色、设置 large title。如果 NavigationBar 在不同屏幕上看起来不同,viewWillAppear 是进行这些更改的正确位置,因为 viewDidLoad 只调用一次。

swift
override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    navigationController?.setNavigationBarHidden(
        false, animated: animated
    )
    navigationController?.navigationBar.prefersLargeTitles = true
    tabBarController?.tabBar.isHidden = false
}

订阅临时通知

仅在屏幕可见时才有意义的通知 — 键盘通知、内容更改通知 — 在 viewWillAppear 中订阅并在 viewDidDisappear 中取消订阅。这可以防止屏幕不活跃时的不必要的处理器,并防止内存泄漏。

恢复 UI 状态

如果屏幕可能被应用程序隐藏或最小化,viewWillAppear 是恢复 UI 状态的便捷位置:切换段、恢复滚动位置、重置临时更改。用户每次出现时都以可预测的形式获得屏幕。

更新徽章和计数器

在显示未读消息、评分或通知计数器的屏幕上,viewWillAppear 是更新它们的正确位置。如果用户可能在另一个屏幕上更改了数量,这里调用重新计算并更新UITabBarItem.badgeValue 或自定义指示器。这确保用户无论在其他屏幕上停留多久,始终看到最新的数字。

单独提一下 collectionView 的工作:如果屏幕上的数据以包含计数器或状态的单元格网格形式呈现,它们在 viewWillAppear 中的更新应该是选择性的。不要完全 reloadData,而是对可见单元格使用 reloadItemsAtIndexPaths,以避免闪烁和丢失滚动位置。

viewWillAppear 与 viewDidLoad 的区别

理解 viewWillAppear 和 viewDidLoad 之间的区别 — 正确 UIViewController 架构的基础。这两种方法具有不同的调用频率、不同的上下文和不同的目的。

viewDidLoad 被调用一次,适用于不随时间变化的配置:注册单元格、设置委托、初始化常量。viewWillAppear 在每次出现时被调用,适用于需要重复的操作:更新数据、配置可见元素、同步状态。

特征viewDidLoadviewWillAppear
频率一次每次出现时
View 可见否(即将可见)
View 尺寸非最终最终
适用于一次性配置更新和同步
动画不适用animated 参数

黄金规则:如果操作只应执行一次 — 放在 viewDidLoad 中。如果每次返回屏幕时都应重复 — 放在 viewWillAppear 中。

viewWillAppear 中的典型错误

错误使用 viewWillAppear 可能导致性能问题、过度更新和界面状态不一致。让我们看看最常见的错误。

第一个错误 — 重复 viewDidLoad 中的逻辑。如果您同时注册表格单元格在 viewDidLoad 和 viewWillAppear 中 — 注册将多次执行,而一次性配置就足够了。将所有一次性配置移到 viewDidLoad 中。

第二个错误 — 每次出现时无条件 reloadData。如果数据没有更改,重新加载表格会导致额外的数据源请求和重绘单元格,降低性能。在调用 reloadData 之前检查状态是否真的发生了变化。

第三个错误 — 处理网络请求时没有考虑到屏幕可能在请求完成前再次被隐藏。如果您在 viewWillAppear 中启动 URLSession 请求,而用户立即转到另一个屏幕,结果可能被应用到已隐藏的 View。使用可取消的任务或在更新前检查 isViewLoaded 和 window。

第四个错误 — 忘记调用 super。不调用 super.viewWillAppear 可能会破坏父控制器(UINavigationController、UITabBarController)的功能,并导致手势和转换的错误处理。super 应该始终被调用。

第五个错误 — 在不调用 layoutIfNeeded 的情况下更改约束。如果在 viewWillAppear 中以编程方式更改约束,UIKit 不会立即应用它们 — 更改会累积到下一次 layout 步骤。要在修改约束后立即应用更改,调用 view.layoutIfNeeded()。这在设置依赖于内容高度的元素时尤为重要。

第六个错误 — 尝试在 viewWillAppear 中执行动画。如上所述,UIKit 仍在处理过渡动画,您的动画可能会与系统动画竞争。如果您需要元素以效果出现,在 viewDidAppear 中使用入场动画,在 viewWillAppear 中只配置初始状态:透明 0,缩放变换 0.8 等。

第七个错误 — 忽略 animated 参数。一些开发者不检查 viewWillAppear 中的 animated 值,并执行应该取决于动画是否存在的操作。例如,在 animated = false 时可以无动画隐藏 NavigationBar,而在 animated = true 时带动画隐藏,以使过渡看起来平滑。始终将 animated 参数传递给相应的 UIKit 方法。

第八个错误 — 在不可见的屏幕上修改 UI。如果在 viewWillAppear 中启动网络请求,并且当屏幕可能已消失时其完成块更新 UI,用户将看到闪烁或不一致的状态。始终在 closures 中更新 UI 之前检查 isViewLoaded 和 window。这个简单的操作可以防止崩溃和不必要的界面重绘。

常见问题

viewWillAppear 和 viewDidAppear 有什么区别?

viewWillAppear 在出现动画开始之前被调用,此时 View 尚不可见。viewDidAppear — 在动画结束后,当屏幕完全显示且可用于交互时被调用。

viewWillAppear 可能不被调用吗?

正常条件下,viewWillAppear 在屏幕出现时总是被调用。例外 — 强制退出应用程序(force quit),此时 UIKit 来不及调用 Lifecycle 方法。

需要调用 super.viewWillAppear 吗?

是的,必须。UIKit 使用此调用与 UINavigationController 和 UITabBarController 进行内部协调。没有 super,手势和过渡动画可能会损坏。

viewWillAppear 在 TabBarController 中多久调用一次?

每次切换标签时。UIKit 在用户点击 TabBar 中相应图标后立即在所选标签控制器上调用 viewWillAppear。

如何通过 viewWillAppear 传回数据?

使用控制器的属性或共享数据源。在调用 popViewController 之前,在前一个控制器上设置所需的值,在其 viewWillAppear 中它们已经可用。

总结

  • viewWillAppear 在每次屏幕出现前被调用,与一次性 viewDidLoad 不同
  • 用于更新表格数据、集合和 UI 状态
  • animated 参数允许将行为调整到带动画和不带动画的过渡
  • NavigationBar、TabBar 和其他导航元素在 viewWillAppear 中配置
  • 临时通知订阅 — 适用于 viewWillAppear 的正确情况
  • 避免重复 viewDidLoad 逻辑和无条件 reloadData
  • 始终调用 super.viewWillAppear 以确保导航正常工作

我们将开发一款交钥匙移动应用程序

IT Sectr自2017年以来为初创企业和企业打造iOS和Android应用程序。我们将为您提供咨询并提出最佳解决方案。

讨论项目

另请阅读