首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在我的堆栈中找到调用的viewController?

如何在我的堆栈中找到调用的viewController?
EN

Stack Overflow用户
提问于 2020-05-29 18:58:07
回答 1查看 547关注 0票数 0

我有一个应用程序,有两个故事板,一个选项卡条控制器和6+ viewControllers嵌入到他们自己的navigationControllers中。

在所有VC中,我以CartViewController的方式呈现barButtonItem,而在购物车中,我从tableViewCell中呈现CustomersVC。我的问题是,当我从购物车中呈现客户时,我可以再次从CustomersVC到购物车,然后继续循环。

假设

我的假设是,如果我从anyVC以模式方式显示购物车,然后从cart以模式方式显示navigationController,然后显示CustomersVC,则会存在这样一个数组:

viewController

  • CartViewController

  • CustomersNavigationController

  • CustomersViewController

  1. Any

为了解决这个问题,如果从购物车中调用"ViewCart“barButtonItem,我将从customersVC中删除它。我的问题是,我无法设法遍历堆栈来检查它。我在这里尝试过几种方法,但都没有用。

我知道我可以使用委托和设置变量来显示/隐藏按钮,但我渴望学习,并且希望它更健壮,而不必记住手动设置和重置var。

有什么建议吗?

代码

代码语言:javascript
复制
extension UIViewController {
    @objc func viewCart() {
        if Cart.sharedInstance.order.items.count != 0 {

            let storyboard = UIStoryboard(name: "Cart", bundle: nil)
            if let cartVC = storyboard.instantiateViewController(withIdentifier: "Cart") as? CartViewController {
                let cartNavigationController = UINavigationController(rootViewController: cartVC)
                self.present(cartNavigationController, animated: true)
            }
        }
    }
}

Class CartViewController {

  let storyboard = UIStoryboard(name: "Main", bundle: nil)
   if let customersNC = storyboard.instantiateViewController(withIdentifier: "CustomersNC") as? UINavigationController {
   present(customersNC, animated: true)

}


class CustomersTableViewController {

override func viewDidLoad() {

// Tried presentingViewController:

    if let CartVC = presentingViewController as? CartViewController {
        myButton.isEnabled = false
    }

// Tried navigationController?.viewControllers:

        guard let controllersInStack = navigationController?.viewControllers else { return }
        if let CartVC controllersInStack.first(where: { $0 is CartViewController }) as? CartViewController  {
            myButton.isEnabled = false
        }

// Tried an extension I found here https://stackoverflow.com/questions/38583941/get-all-list-of-uiviewcontrollers-in-ios-swift, but it returns nil

extension UIViewController {
   /**
    * Traverses the entire VC hirearchy downwards and collects VC'w that are of speccific PARAM: type
    * - Fixme: ⚠️️ this can be written more elegantly with flatMap
    * ## Example:
    * let vc: CustomVC? = UIApplication.shared.delegate?.window?.rootViewController?.descendants().first
    */
   func descendants<T>(type: T.Type? = nil) -> [T] {
       var childrenOfType: [T] = []
       self.children.forEach {
           if let child: T = ($0 as? T) {
               childrenOfType.append(child)
           }
           if !$0.children.isEmpty {
               childrenOfType += $0.descendants(type: type)
           }
       }
       return childrenOfType
   }
}
EN

Stack Overflow用户

回答已采纳

发布于 2020-05-29 19:25:19

每个视图控制器都有一个parent或一个presentingViewController (或者两者都有),因此通过询问这些内容,您可以确定“您在哪里”。

这通常足以告诉您情况,特别是如果您明智地使用类类型(例如,您可以使导航控制器不同的UINavigationController子类只是为了知道您以后在哪里)。

如果您想要一个完整的视图控制器链的简介到您所在的位置,您可以递归地在该链上跟踪您的方式,如下所示:

代码语言:javascript
复制
func trace(_ vc: UIViewController) {
    print(vc)
    if let parent = vc.parent {
        print("parent:")
        trace(parent)
        return
    }
    if let presenter = vc.presentingViewController {
        print("presenter:")
        trace(presenter)
        return
    }
    print("done")
}

该示例输出的不是一个视图控制器列表,而是每个视图控制器之间连接的性质(这是您真正需要的),但是通过从链中的“最后”视图控制器调用它,您可以在想要说“不要再深入一点”的时候,对链的样子有一个心理上的了解。

下面是一个更完整的示例,演示如何将反向跟踪积累到数组中:

代码语言:javascript
复制
class MyVC: UIViewController {
    func makeTrace() {
        super.viewDidAppear(animated)
        let result = self.trace([(.start, self)])
        print(result)
    }
    enum Link: String {
        case parent
        case presenter
        case start
    }
    typealias Chain = [(Link, UIViewController)]
    func trace(_ chain: Chain) -> Chain {
        if let parent = chain.last!.1.parent {
            return trace(chain + [(.parent, parent)])
        }
        if let presenter = chain.last!.1.presentingViewController {
            return trace(chain + [(.presenter, presenter)])
        }
        return chain
    }
}

所以result会告诉你足够多的信息,让你知道“你在哪里”。

票数 1
EN
查看全部 1 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62092946

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档