首页 > 解决方案 > 如何在tabBarController中连接VC throw navController以快速传递数据

问题描述

当点击 tabBar 项时,我正在尝试更改 VC 中标签的文本。但是在我将 UINavigationController 嵌入到 VC 之后,我在点击 tabBar 时崩溃了(线程 1:致命错误:在隐式展开可选值时意外发现 nil)。有人知道如何解决吗?这是碰撞线的照片

import UIKit

class TabBarController: UITabBarController, UITabBarControllerDelegate {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.delegate = self
        
    }
    
    
    
    func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
        if tabBarController.selectedIndex == 3{
            
            let navVC = tabBarController.viewControllers![3] as? UINavigationController
            let bagPageVC = navVC?.topViewController as? bagPage
            
            bagPageVC!.stringCountOfHP = "\(String(bagPageVC!.countArray)) items in bag"
            bagPageVC?.tableView.reloadData()
            
        }
        
    }
}

标签: iosswiftuiviewcontrolleruinavigationcontrolleruitabbarcontroller

解决方案


这应该可以帮助您的代码避免崩溃,

    func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
        if tabBarController.selectedIndex == 3{
            if let navVC = tabBarController.viewControllers?[3] as? UINavigationController,
               let bagPageVC = navVC.topViewController as? bagPage {
            bagPageVC.countOfHP.text = "\(String(bagPageVC.countArray)) items in bag"

        }
    }

崩溃可能有多种原因

1.tabBarController.viewControllers可能返回零,

  1. tabBarController.viewControllers![3] as! UINavigationController尽管在索引 3 处存在视图控制器,但它可能不是UINavigationController或子类UINavigationController

  2. 包页VC!可能为零,因此强制展开可能会使其崩溃,因为navVC.topViewController不是bagPage

如果不正确查看您的 ViewController 设置 n 层次结构,则无法为您提供更多帮助。

上面的代码将安全地解开所有的选项,所以它不会让你的代码崩溃

编辑1:

问题第一次发生,当您点击索引 3ViewController处的选项卡栏时,该索引在屏幕上尚不可见,因此显然它的所有IBOutlets 都为零,并且当您盲目访问隐式可选 IBOutletbagPageVC.countOfHP时,它会崩溃。

你能做什么?

我能想到的两种可能的解决方案

解决方案1:

func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
        if tabBarController.selectedIndex == 3,
           let bagPageVC = (viewController as? UINavigationController)?.topViewController as? bagPage {
            let _ = bagPageVC.view //this statement will force the view controller to load its view hence `ViewDidLoad` will be called automatically for the first time (which anyway would have called you are just fast tracking it
            bagPageVC.countOfHP.text = "\(String(bagPageVC.countArray)) items in bag"
        }
    }

didSelect viewController每次用户选择不同的选项卡时都会被调用,但let _ = bagPageVC.view只会ViewDidLoad被调用一次(一旦加载视图,当您访问.view它时只会返回视图)

虽然这段代码可以正常工作,没有任何问题,但我不太喜欢干预 View 周期,因此解决方案 2

解决方案2:

检查隐式可选IBOutlet是否为nil,如果不是,则简单地设置文本,否则将文本传递给bagPageVC并将其设置为ViewDidLoad

func tabBarController(_ tabBarController: UITabBarController, didSelect viewController: UIViewController) {
        if tabBarController.selectedIndex == 3,
           let bagPageVC = (viewController as? UINavigationController)?.topViewController as? bagPage {
            if let countLabel = bagPageVC.countOfHP {
                  countLabel.text = "\(String(bagPageVC.countArray)) items in bag"
            }
            else {
                 bagPageVC.countInfo = "\(String(bagPageVC.countArray)) items in bag"
            }
        }
    }

现在在您bagPageVC声明一个名为的countInfo变量String?

var countInfo: String? = nil

ViewDidLoad可以简单地设置

override func viewDidLoad() {
     super.viewDidLoad()
     countOfHP.text = countInfo
}

ViewDidLoad在 ViewController 的生命周期中只被调用一次,因此您不必担心countInfo在后续didSelect viewController调用中重置

你会选择哪一个我留给你:)


推荐阅读