Öffnen des View Controllers vom App-Delegaten mit Swift


73

Ich versuche, eine Push-Benachrichtigung zu erstellen, die anhand der aus dem Push erhaltenen Informationen festlegt, welche Ansicht geöffnet werden soll.

Ich habe es geschafft, die Informationen aus dem Push zu erhalten, aber ich habe jetzt Probleme, die Ansicht zu öffnen

Bei anderen Fragen zum Stapelüberlauf habe ich derzeit Folgendes:

App-Delegierter hat das Laden beendet:

     //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

                        }
    }

Derzeit schlägt dies in der Zeile var ViewController = self ... fehl.


Überprüfen Sie diese Antwort
Borzh

2
Ich habe es versucht und es funktioniert so weit wie das Öffnen des View-Controllers "Circles". Angenommen, der View Controller "Circles" befindet sich selbst in einem Unterbaum des Navigationsbaums meiner App. Wie stelle ich sicher, dass nach dem Öffnen meiner App im View-Controller "Circles" alle Rückennavigationen funktionieren? Im Moment wird der Ansichts-Controller "Kreise" geöffnet, ohne dass die Rückennavigation angezeigt wird.
Dogahe

Antworten:


112

Sie müssen die ViewController StoryBoardId-Eigenschaft wie im folgenden Bild festlegen.

Geben Sie hier die Bildbeschreibung ein

Öffnen Sie den viewController mit der folgenden Codierung in Kürze

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
    }

Für iOS 13+ (basierend auf einem Artikel von dev2qa )
Öffnen SceneDelegate.swiftund fügen Sie Folgendes hinzu

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

Es gibt ein Open-Source- Navigationsprogramm, das versucht, dies zu vereinfachen. Beispiel


2
Dadurch wird jedoch eine neue Instanz des Controllers erstellt. Ich möchte den Controller, der bereits Status hat. Oder fehlt mir etwas?
rjcarr

Die App-Delegate-Methode wird beim Empfang einer Benutzerbenachrichtigung nicht aufgerufen. Warum?
ArgaPK

Gleiches gilt für schnelle Vertion, jedoch nur für Syntaxänderungen.
Kirit Modi

aber viewDidLoad funktioniert nicht in diesem viewController ("Kreise")
Rashid KC

1
Spätestens: Geben Sie den AntwortcodeSceneDelegate.scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) ein (FYI, ich habe ein Navigationsprogramm basierend darauf erstellt )
Hassan Tareq

49

Swift 3:

Dies ist mein bevorzugter Ansatz, wenn ich einen neuen viewController vom aktuellen viewController über das AppDelegate präsentiere. Auf diese Weise müssen Sie Ihre Ansichtshierarchie beim Behandeln einer Push-Benachrichtigung oder eines universellen Links nicht vollständig auflösen

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

2
Dies ist der beste Ansatz. Sie können diese Ansicht auch schließen. Self.dismiss (animiert: true, Vervollständigung: null)
Imtee

@Imtee: Entlassen Sie den präsentierten viewController, den Sie meinen?
Lohith Korupolu

@LohithKorupolu, wenn Sie vom aktuellen Ansichts-Controller wechseln möchten.
Imtee

Das hat bei mir funktioniert, gut gemacht! Ich habe dies in die applicationWillEnterForegroundMethode meines appDelegate eingefügt, um einen Neustart meiner App auf dem Begrüßungsbildschirm beim erneuten Öffnen zu erzwingen (auf diese Weise kann ich meine Daten und die Benutzeroberfläche ordnungsgemäß aktualisieren, indem ich ein einfaches "All-through-One-Path" -Modell pflege lol :) Danke!
Justin

Perfekt, danke.
Mostafa Sh

11

Swift 3

So präsentieren Sie die Ansicht zusammen mit dem Navigationscontroller:

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

Das funktioniert ... aber wenn Sie eine TabBar haben, wird die TabBar nicht angezeigt.
Xhinoda

7

Initialisieren Sie zuerst die window

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

Zum Einstellen rootViewControllerinnerhalb der AppDelegateKlasse

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

6

Es gibt eine schnelle 4-Version

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}

5

In 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")
        }

3

Ich würde sagen, dass es eine schlechte Idee ist, UIWindow jedes Mal zu erstellen, wenn Sie rootViewController ändern möchten. Nach einigen Änderungen an rootVC (unter Verwendung der oberen Lösung) haben Sie viele UIWindows gleichzeitig in Ihrer App.

Meiner Meinung nach ist eine bessere Lösung:

  1. Holen Sie sich neue rootVC: let rootVC = UIStoryboard(name: "StoryboardName", bundle: nil).instantiateViewControllerWithIdentifier("newRootVCIdentifier") as UIViewController
  2. Legen Sie den Rahmen für die neue rootVC aus den Grenzen von UIScreen fest: rootVC.view.frame = UIScreen.mainScreen().bounds
  3. Neuen Root-Controller für aktuelles Fenster einstellen (hier mit Animation): UIView.transitionWithView(self.window!, duration: 0.5, options: .TransitionCrossDissolve, animations: { self.window!.rootViewController = rootVC }, completion: nil)

Erledigt!

Sie benötigen keine Methode window?.makeKeyAndVisible(), da diese Lösung im aktuellen App-Fenster funktioniert.


Wie kann man diesen VC entlassen?
Krutika Sonawala

3

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

Der Navigationscontroller wird gleich Null, wenn ich die App mit diesem Code aus der Erweiterung öffne. Haben Sie eine Problemumgehung?
al_mukthar

1
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)

0

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)
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.