【问题标题】:Opening view controller from app delegate using swift使用 swift 从应用程序委托打开视图控制器
【发布时间】:2015-08-16 00:51:05
【问题描述】:

我正在尝试创建一个推送通知,它根据从推送中获得的信息确定要打开哪个视图。

我已经设法从推送中获取信息,但我现在正在努力打开视图

查看其他堆栈溢出问题,我目前有以下问题:

App Delegate 是否完成加载:

     //Extract the notification data
    if let notificationPayload = launchOptions?[UIApplicationLaunchOptionsRemoteNotificationKey] as? NSDictionary {
        // Get which page to open
        let viewload = notificationPayload["view"] as? NSString
        let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
        //Load correct view
        if viewload == "circles" {

            var viewController = self.window?.rootViewController?.storyboard?.instantiateViewControllerWithIdentifier("Circles") as! UIViewController
            self.window?.rootViewController = viewController

                        }
    }

目前这在 var ViewController = self... 行上失败了。

【问题讨论】:

  • 查看this答案
  • 我试过这个,它可以打开“Circles”视图控制器。但是,假设“Circles”视图控制器本身位于我的应用程序导航树的子树中。我如何确保在“Circles”视图控制器中打开我的应用程序后,所有后退导航都有效?现在,它会打开“Circles”视图控制器而不显示后退导航。

标签: ios swift uiviewcontroller appdelegate


【解决方案1】:

您必须如下图所示设置 ViewController StoryBoardId 属性。

在swift中使用如下编码打开viewController

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

         let mainStoryboardIpad : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
         let initialViewControlleripad : UIViewController = mainStoryboardIpad.instantiateViewControllerWithIdentifier("Circles") as UIViewController
         self.window = UIWindow(frame: UIScreen.main.bounds)
         self.window?.rootViewController = initialViewControlleripad
         self.window?.makeKeyAndVisible()

         return true
    }

适用于 iOS 13+(基于 an article by dev2qa
打开SceneDelegate.swift并添加以下内容

func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {

    // If this scene's self.window is nil then set a new UIWindow object to it.
    self.window = self.window ?? UIWindow()

    // Set this scene's window's background color.
    self.window!.backgroundColor = UIColor.red

    // Create a ViewController object and set it as the scene's window's root view controller.
    self.window!.rootViewController = ViewController()

    // Make this scene's window be visible.
    self.window!.makeKeyAndVisible()

    guard scene is UIWindowScene else { return }
}

有一个开源的navigation utility 试图让这更容易。 Example

【讨论】:

  • 但这是创建控制器的一个新实例。我想要已经有状态的控制器。还是我错过了什么?
  • 收到用户通知时没有调用app代理方法,为什么?
  • 同样适用于快速版本,但只有语法改变。
  • 但是 viewDidLoad 在那个 viewController ("circles") 中不起作用
  • 最新:将答案代码放入SceneDelegate.scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) (仅供参考,我根据this创建了一个navigation util
【解决方案2】:

首先初始化window

self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
let storyBoard = UIStoryboard(name: "Main", bundle: nil)

用于在AppDelegate 类中设置rootViewController

let viewController = storyBoard.instantiateViewControllerWithIdentifier("Circles") as UIViewController
self.window?.rootViewController = viewController
self.window?.makeKeyAndVisible()

【讨论】:

    【解决方案3】:

    我会说每次您想更改 rootViewController 时创建 UIWindow 是个坏主意。在对 rootVC 进行几次更改(使用上层解决方案)之后,您的应用程序中将同时拥有多个 UIWindows。

    我认为更好的解决方案是:

    1. 获取新的rootVC:let rootVC = UIStoryboard(name: "StoryboardName", bundle: nil).instantiateViewControllerWithIdentifier("newRootVCIdentifier") as UIViewController
    2. 从 UIScreen 的边界为新的 rootVC 设置框架:rootVC.view.frame = UIScreen.mainScreen().bounds
    3. 为当前窗口设置新的根控制器(这里有动画):UIView.transitionWithView(self.window!, duration: 0.5, options: .TransitionCrossDissolve, animations: { self.window!.rootViewController = rootVC }, completion: nil)

    完成!

    您不需要方法window?.makeKeyAndVisible(),因为此解决方案适用于当前应用程序窗口。

    【讨论】:

    • 如何关闭这个vc?
    【解决方案4】:

    斯威夫特 3:

    当通过 AppDelegate 从当前 viewController 呈现新的 viewController 时,这是我的首选方法。这样,您在处理推送通知或通用链接时不必完全拆除视图层次结构

    if let controller = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "someController") as? SomeController {
        if let window = self.window, let rootViewController = window.rootViewController {
            var currentController = rootViewController
            while let presentedController = currentController.presentedViewController {
                currentController = presentedController
            }
            currentController.present(controller, animated: true, completion: nil)
        }
    }
    

    【讨论】:

    • 这是最好的方法,你也可以关闭这个视图 self.dismiss(animated: true, completion: nil)
    • @Imtee:你的意思是关闭呈现的 viewController?
    • @LohithKorupolu,如果你想从当前的视图控制器移动。
    • 这对我有用,干得好!我把它放在我的 appDelegate 的applicationWillEnterForeground 方法中,以便在重新打开时强制在初始屏幕上重新启动我的应用程序(这样,我可以通过维护一个简单的“通过一条路径”模型来正确刷新我的数据和 UI,哈哈 :)谢谢!
    • 完美,谢谢。
    【解决方案5】:

    斯威夫特 3

    与导航控制器一起呈现视图:

    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    let viewController = storyboard.instantiateViewController(withIdentifier :"InboxViewController") as! InboxViewController
    let navController = UINavigationController.init(rootViewController: viewController)
    
       if let window = self.window, let rootViewController = window.rootViewController {
           var currentController = rootViewController
           while let presentedController = currentController.presentedViewController {
               currentController = presentedController
            }
               currentController.present(navController, animated: true, completion: nil)
       }
    

    【讨论】:

    • 这行得通...但是如果你有一个 tabBar,tabBar 是不显示的。
    【解决方案6】:

    Swift 3 SWRevealViewController

        self.window = UIWindow(frame: UIScreen.main.bounds)
        let storyBoard = UIStoryboard(name: "Main", bundle: nil)
    
        let viewController = storyBoard.instantiateViewController(withIdentifier: "SWRevealViewController") as! SWRevealViewController
        self.window?.rootViewController = viewController
        self.window?.makeKeyAndVisible()
    

    【讨论】:

    • navigationcontroller 变为 nil 如果我使用此代码从扩展中打开应用程序.. 你有任何解决方法吗?
    【解决方案7】:

    在 Swift 3 中

            let mainStoryboard : UIStoryboard = UIStoryboard(name: StorybordName, bundle: nil)
            let initialViewControlleripad : UIViewController = mainStoryboard.instantiateViewController(withIdentifier: identifierName) as UIViewController
            if let navigationController = self.window?.rootViewController as? UINavigationController
            {
                navigationController.pushViewController(initialViewControlleripad, animated: animation)
            }
            else
            {
                print("Navigation Controller not Found")
            }
    

    【讨论】:

      【解决方案8】:
      let storyboard = UIStoryboard(name: "Main", bundle: nil)
      
          let destinationViewController = storyboard.instantiateViewController(withIdentifier: "LandVC") as! LandingPageVC
      
          destinationViewController.webpageURL = NotificationAdvertisement._htmlpackagePath
          destinationViewController.adID = NotificationAdvertisement._adID
          destinationViewController.toneID = NotificationAdvertisement.toneID
      
          let navigationController = self.window?.rootViewController as! UIViewController
      
          navigationController.showDetailViewController(destinationViewController, sender: Any?.self)
      

      【讨论】:

        【解决方案9】:

        有一个swift 4版本

        func application(_ application: UIApplication, 
        didFinishLaunchingWithOptions launchOptions: 
        [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        let mainStoryboardIpad : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
        let initialViewControlleripad : UIViewController = mainStoryboardIpad.instantiateViewController(withIdentifier: "Circles") as UIViewController
                    self.window = UIWindow(frame: UIScreen.main.bounds)
                    self.window?.rootViewController = initialViewControlleripad
                    self.window?.makeKeyAndVisible()
        
        return true}
        

        【讨论】:

          【解决方案10】:

          SWIFT 4

          let storyboard = UIStoryboard(name: "Main", bundle: nil)
          
              let destinationViewController = storyboard.instantiateViewController(withIdentifier: "LandVC") as! LandingPageVC
          
              destinationViewController.webpageURL = NotificationAdvertisement._htmlpackagePath
              destinationViewController.adID = NotificationAdvertisement._adID
              destinationViewController.toneID = NotificationAdvertisement.toneID
          
              let navigationController = self.window?.rootViewController as! UIViewController
          
              navigationController.showDetailViewController(destinationViewController, sender: Any?.self)
          

          【讨论】:

            猜你喜欢
            • 2020-09-20
            • 2013-10-29
            • 1970-01-01
            • 1970-01-01
            • 2015-08-22
            • 2011-12-29
            • 2013-10-26
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多