【问题标题】:How to connect VC throw navController in tabBarController to pass data in swift如何在tabBarController中连接VC throw navController以快速传递数据
【发布时间】:2021-05-26 18:01:36
【问题描述】:

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

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()
            
        }
        
    }
}

【问题讨论】:

  • let bagPageVC = navVC.topViewController as? bagPagetabBarController.viewControllers![3] as! UINavigationController 这必须返回 nil,添加 if letguard let 以进一步调试

标签: ios swift uiviewcontroller uinavigationcontroller uitabbarcontroller


【解决方案1】:

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

    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 可能返回 nil,

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

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

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

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

编辑 1:

第一次出现问题,当您点击索引 3 处的标签栏时,该索引处的ViewController 在屏幕上尚不可见,因此显然它的所有IBOutlets 都是 nil,当您盲目访问隐式可选 IBOutlet bagPageVC.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的生命周期中只被调用一次,所以你不必担心在后续的didSelect viewController调用中重置countInfo

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

【讨论】:

  • 它崩溃了。我尝试打印 bagPageVC,它打印了正确的 VC
  • 使用此代码后是否崩溃?能否添加崩溃截图
  • 我在问题中添加了屏幕截图
  • 崩溃清楚地表明您的countOfHP 标签为零,这是 IBOutlet 吗?是否正确连接?如果 IBOutlet 未连接到故事板中的 UIComponent 或 UI 尚未加载,则 IBOutlet 可以为 nil,但如果这是选项卡栏控制器视图控制器之一,我相信 ViewDidLoad 已经在所有 ViewControllers 上调用,所以剩下的唯一可能性是IBOutlet 未连接
  • 非常感谢您的帮助。我使用第一种方法作为解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-08-20
  • 2018-07-27
相关资源
最近更新 更多