从自定义 UIViewController 导航到 TabBarController 而不使用 segue

Posted

技术标签:

【中文标题】从自定义 UIViewController 导航到 TabBarController 而不使用 segue【英文标题】:Navigate from a Custom UIViewController to a TabBarController without segue 【发布时间】:2018-07-02 17:19:24 【问题描述】:

当我从自定义 UIViewController 导航到 TabBarController 的第二个选项卡时遇到问题,这当然是另一个 UIViewController。 如果我从 AdminPanel 导航到 Products 不会崩溃,因为我有一个从 Products 到 AdminPanel 的push。但是从 AdminPanel 到购物车我没有任何 push

这是有错误的图片:

这是错误:“无法将 'MyAppName.AdminPanelViewController' (0x10e878418) 类型的值转换为 'MyAppName.ProductsViewController' (0x10e877e00)。”

这是我的设计:

这是我的代码:

    // PRODUCTS VC
    class ProductsViewController: UIViewController

var selectedProductsArray = [Product]()
    var priceForSelectedProductsArray = [Float]()

       // Func which is using GestureRecognition to access the Admin Panel when we press on User Avatar
        func accessToAdminPanel()

            let tapGesture = UITapGestureRecognizer(target: self, action: #selector(ProductsViewController.adminImageTapped(gesture:)))

            userAvatarImageView.addGestureRecognizer(tapGesture)
        

        // Function to open the AdminPanelViewController
        @objc func adminImageTapped(gesture: UIGestureRecognizer) 

            let storyBoard : UIStoryboard = UIStoryboard(name: Constants.nameOfMainSB, bundle:nil)
            let adminPanelVC = storyBoard.instantiateViewController(withIdentifier: Constants.adminPanelStoryboard) as! AdminPanelViewController
            self.navigationController?.pushViewController(adminPanelVC, animated: true)

        


        // Func which will add the product into an array of products when the user press Add To Cart
        func didTapAddToCart(_ cell: ProductTableViewCell) 
            let indexPath = self.productsTableView.indexPath(for: cell)

            addProduct(at: indexPath!)
            selectedProductsArray.append(productsArray[(indexPath?.row)!]) // Append products for cart
            priceForSelectedProductsArray.append(productsArray[(indexPath?.row)!].price) // Append prices for selected products
        

    


    // CART VC
    class CartViewController: UIViewController 

 var productsInCartArray = [Product]()
    var productPricesArray = [Float]()

     // Append the selectedProducts into productsInCartArray using the TabBarController
        func fetchSelectedProducts() 

    // ------------------HERE IS CRASHING AT THIS LINE -----------------------
            productsInCartArray = ((self.tabBarController?.viewControllers![0] as! UINavigationController).topViewController as! ProductsViewController).selectedProductsArray
            productPricesArray = ((self.tabBarController?.viewControllers![0] as! UINavigationController).topViewController as! ProductsViewController).priceForSelectedProductsArray
            totalSum = productPricesArray.reduce(0, +)
        

    

如果您无法通过这部分代码找出崩溃的地方,我可以给您指向 git 源代码的链接,因为我没有什么要隐藏的。

非常感谢您在阅读本文时抽出宝贵时间,希望您能帮助我,因为我花了半天时间试图找到一个解决方案来修复这个导致我的应用程序崩溃的错误。

【问题讨论】:

【参考方案1】:

topViewController 现在是管理员而不是产品,因此您需要在索引 0 处获取 VC,即产品

productsInCartArray = ((self.tabBarController?.viewControllers![0] as! UINavigationController).viewControllers[0] as! ProductsViewController).selectedProductsArray

【讨论】:

在哪里添加那行代码?我需要 AdminPanel 中的函数? 您当前的代码不包含崩溃点的位置,请将您投射到的代码附上as! ProductsViewController 但是在我的帖子里。我还添加了一条评论“这里正在崩溃”【参考方案2】:

错误告诉您,您正在尝试将 AdminPanelViewController 强制为 ProductsViewController(在该行的 topViewController as! ProductsViewController 部分。)这是因为当您推送到 AdminPanelViewController 时,它会移动到导航堆栈的顶部,替换您假设应该存在的 ProductsViewController。

短期内有很多方法可以处理这个错误,比如遍历导航栈而不是仅仅抓取topViewController,像这样:

guard let navController = self.tabBarController?.viewControllers![0] as? UINavigationController else 
    // handle error
    return

for controller in navController.viewControllers 
    if let productsController = controller as? ProductsViewController 
        // do work here
    

但我认为,从根本上讲,您必须重新考虑如何访问事物。一般来说,您不应该在导航堆栈中进行工作。导航堆栈时最好在控制器之间传递数据。

另外,您应该尽量避免使用as! 强制转换,而应使用as?,这样您就可以捕获在应用程序崩溃的情况下无法进行转换的情况。我个人的目标是只在 IBOutlet 声明中使用!,而不是在其他任何地方,但你的里程可能会有所不同。

【讨论】:

以上是关于从自定义 UIViewController 导航到 TabBarController 而不使用 segue的主要内容,如果未能解决你的问题,请参考以下文章

从自定义 UIPopOver 问题推送新的 UIViewController

从自定义导航栏展开 segue 后,如何切换回默认导航栏外观?

Segue 未从自定义 tableView 单元格触发

如何从自定义导航栏中删除这条黑线

从自定义 NSObject 内部视图推送导航应用程序中的新视图

从自定义单元笔尖推送到 viewController