ios 如何从UIViewController或视图外部推送ViewController?

nszi6y05  于 2023-03-05  发布在  iOS
关注(0)|答案(2)|浏览(120)

我希望能够从类导航视图(singletons)与视图没有连接。原因是数据更改(例如,作为网络调用的结果)在完成显示视图后的某个时间点。例如,应用程序(某类)可能仅在一秒钟后才知道用户之前是否打开过应用程序,并应转到主视图,或查看某个入职视图。
我将UINavigationController中的UIViewController作为应用程序的起点。业务逻辑与Manager单例中的视图部分分开,如下所示:

class ExampleManager: NSObject {
    
    static var shared: ExampleManager = ExampleManager()
    
    public override init() {
        super.init()
        
        SwiftSingletons.register(self)
    }
}

这样我就可以在它们之间进行交互通信。现在让我们假设在ExampleManager的一个函数中,在其初始化后的第二秒-管理器知道(通过数据隐式地)导航到视图A或B。但是我怎样才能从这个管理器中触发导航到这些视图之一?
我想这可以通过以下两种方式来实现:

  • 使用合并/通知(观察ViewController内的数据)
  • 问题:这感觉像是一个非常简单的解决方案。
  • 使用ViewController内部的静态函数,该函数可以从外部调用
  • 问题:navigationController?.pushViewController(controller, animated: true)是不可能的,因为 “示例成员”navigationController“不能用于类型”ViewController“”
  • 或者SwiftUI中可能有类似@ObservedObject的方法,在数据更改时触发视图/ ViewController重新计算?
t40tm48m

t40tm48m1#

抱歉,我没有足够的声誉来评论,但是我强烈建议你研究一下协调器模式!它的工作方式和你试图使用这些单例的方式是一样的。
你给予VC一个“coordinator”(只是一个对象),它处理视图/VC之间的导航,VC自己实际上并不知道谁连接到谁,但coordinator处理这个。
https://www.hackingwithswift.com/articles/71/how-to-use-the-coordinator-pattern-in-ios-apps
为了更直接地回答你的问题,你可以给予你的对象ExampleManager一个navigationController或view控制器的访问权限,它会处理pushing / popping,但是它不知道它到底要去哪个视图或者从哪个视图来(见我上面的链接)。

s8vozzvw

s8vozzvw2#

需要UIViewController类或UIViewController子类的示例来访问navigationController,然后您就可以轻松地在UIViewController之间导航。要获取UIViewController或其子类的示例,您可以简单地使用以下函数,为了使其具有可重用性,您应该对UIApplication进行扩展,以便从任何类型的类(即Singleton/Model/Modal/UIView/Custom等)轻松访问。

extension UIApplication {
    class func getTopViewController(rootVC: UIViewController? = UIApplication.shared.keyWindow?.rootViewController) -> UIViewController? {
        if let navigationVC = rootVC as? UINavigationController {
            return getTopViewController(rootVC: navigationVC.visibleViewController)
        } else if let tabVC = rootVC as? UITabBarController, let selectedVC = tabVC.selectedViewController {
            return getTopViewController(rootVC: selectedVC)
        } else if let presentedVC = rootVC?.presentedViewController {
            return getTopViewController(rootVC: presentedVC)
        }
        return rootVC
    }
}

用法:

guard let topVC = UIApplication.getTopViewController() else { return }
        topVC.navigationController?.pushViewController(controller: SigninViewController(), animated: true)

此外,如果要检查当前所在的UIViewController类,请使用以下代码检查UIViewController的类型:

guard let topVC = UIApplication.getTopViewController() else { return }
        if topVC.isKind(of: SigninViewController.self) {
            // your code
        }

如果您不关心UIViewController的类型/子类,那么您可以直接这样使用:

guard let rootVC = UIApplication.shared.keyWindow?.rootViewController else { return }
        rootVC.navigationController?.pushViewController(SigninViewController(), animated: true)

相关问题