使用UITabBarController时如何在视图控制器之间传递数据
标签栏控制器场景下视图控制器数据传递解决方案
触发机制说明
标签栏控制器与子控制器之间的relationship segue属于初始化关联类segue,仅在控制器初始化阶段完成子控制器的绑定,不属于页面跳转过渡类segue。只有show、present modally这类用户触发的过渡型segue才会调用prepare(for: segue)方法,标签切换时不会重新触发segue流程,因此该方法不会被回调。
故事板中relationship segue提供的selector属性为系统内部绑定标签项与控制器的专属配置,无法用来识别用户点击的标签项,无需在该属性上做适配开发。
可行实现方案
下面提供3种适配不同场景的实现方案:
方案1:使用UITabBarControllerDelegate代理实时赋值
该方案适合每次切换标签时都需要传递动态更新数据的场景,通过代理回调可以实时拿到当前选中的目标控制器直接赋值。
实现代码参考:
// 自定义标签栏控制器类 class CustomTabBarController: UITabBarController { override func viewDidLoad() { super.viewDidLoad() // 设置代理为自身 delegate = self } } // 实现代理方法 extension CustomTabBarController: UITabBarControllerDelegate { func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) { // 1. 按控制器类型匹配赋值 if let targetVC = viewController as? TargetViewController { targetVC.receivedData = "需要传递的动态数据" } // 2. 也可通过下标区分不同标签 guard let index = tabBarController.viewControllers?.firstIndex(of: viewController) else { return } switch index { case 0: // 给第一个标签的控制器赋值 break case 1: // 给第二个标签的控制器赋值 break default: break } } }
方案2:初始化阶段提前给子控制器赋值
该方案适合传递静态数据、不需要每次切换标签更新数据的场景,性能损耗更低。
实现代码参考:
class CustomTabBarController: UITabBarController { override func viewDidLoad() { super.viewDidLoad() // 遍历所有子控制器提前赋值 guard let viewControllers = viewControllers else { return } for (index, vc) in viewControllers.enumerated() { if let firstVC = vc as? FirstViewController, index == 0 { firstVC.staticData = "首页静态数据" } else if let secondVC = vc as? SecondViewController, index == 1 { secondVC.staticData = "第二页静态数据" } } } }
方案3:通过共享状态/通知中心实现跨页面数据传递
如果需要传递的数据需要在多页面共享、且数据会动态更新,可以使用单例存储共享数据,或者通过NotificationCenter在数据变更时向目标控制器发送通知更新内容,适合复杂业务场景下的多页面数据同步。
相关截图

内容的提问来源于stack exchange,提问作者Laura Ruival
相关产品推荐
相关产品推荐

