Instanziieren und Präsentieren eines viewControllers in Swift

300

Problem

Ich begann einen Blick von der neuen Einnahme Swiftauf Xcode 6, und ich versuchte , einige Demo - Projekte und Tutorials. Jetzt stecke ich fest bei:

Instanziieren und dann Präsentieren viewControllereines bestimmten Storyboards

Ziel-C-Lösung

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"myStoryboardName" bundle:nil];
UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:@"myVCID"];
[self presentViewController:vc animated:YES completion:nil];

Wie erreicht man das auf Swift?

E-Riddie
quelle

Antworten:

648

Diese Antwort wurde zuletzt für Swift 5.2 und iOS 13.4 SDK überarbeitet.


Es ist alles eine Frage der neuen Syntax und leicht überarbeiteter APIs. Die zugrunde liegende Funktionalität von UIKit hat sich nicht geändert. Dies gilt für die überwiegende Mehrheit der iOS SDK-Frameworks.

let storyboard = UIStoryboard(name: "myStoryboardName", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "myVCID")
self.present(vc, animated: true)

Wenn Sie Probleme mit haben init(coder:), lesen Sie bitte die Antwort von EridB .

akashivskyy
quelle
3
Sie können sogar das weglassen ;! ;) Würde es dir etwas ausmachen, auf das as UIViewControllereinzugehen? Warum ist das notwendig?
Sebastian Wramba
5
asDas Schlüsselwort wird für die Typumwandlung verwendet. Es ist das gleiche wie (UIViewController *)anObjectin Ziel c
Garoal
1
Ja, ich weiß, dass ich sie weglassen kann, aber das ist ein Teil des langen Habbits. : D als instantiateViewControllerWithIdentifierRücksendungen AnyObject( idäquivalent in Swift) und I erklären , vcwie UIViewController, I Rolle festgelegt haben , AnyObjectum UIViewController.
Akashivskyy
Hallo Freunde, ich habe ein anderes Problem. Dieser Code läuft auf einem Simulator, nicht auf meinem iPad2 mit iOS v7.1.2. Wenn es Ihnen nichts ausmacht, helfen Sie mir, dieses Problem zu beheben.
Indra
3
@akashivskyy Auf jeden Fall für Sie. Aber vielleicht nicht zu einigen.
mmc
43

Für Leute, die @ akashivskyys Antwort verwenden, um zu instanziieren UIViewControllerund die Ausnahme haben:

Schwerwiegender Fehler: Verwendung des nicht implementierten Initialisierers 'init (coder :)' für die Klasse

Kurzer Tipp:

Implementieren required init?(coder aDecoder: NSCoder)Sie manuell an Ihrem Ziel UIViewController, das Sie instanziieren möchten

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
}

Wenn Sie weitere Beschreibungen benötigen, lesen Sie bitte meine Antwort hier

E-Riddie
quelle
Wenn Sie einen benutzerdefinierten Initiator verwenden möchten, können Sie den Super einfach mit super.init (nibName: nil, bundle: nil) aufrufen, und der Puh wird gut geladen oder mit dem Namen der NIB-Datei aufgerufen.
user1700737
4
@ user1700737 Ich instanziiere den viewController unter Bezugnahme auf das Storyboard, das initWithCoder und nicht initWithNib ausführt. Siehe diese Frage stackoverflow.com/questions/24036393/…
E-Riddie
Hallo Freunde, ich habe ein anderes Problem. Dieser Code läuft auf einem Simulator, nicht auf meinem iPad2 mit iOS v7.1.2. Wenn es Ihnen nichts ausmacht, helfen Sie mir, dieses Problem zu beheben.
Indra
@Indra du musst noch eine Frage auf Stack stellen, gib mir den Link Ich werde dir gerne helfen!
E-Riddie
Auf Swift 1.2 müssen Sie init(coder aDecoder: NSCoder!)"erforderlich" machen. Also jetzt müssen Sie Folgendes schreiben:required init(coder aDecoder: NSCoder!)
Eduardo Viegas
18

Dieser Link hat beide Implementierungen:

Schnell:

let viewController:UIViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("ViewController") as UIViewController
self.presentViewController(viewController, animated: false, completion: nil)

Ziel c

UIViewController *viewController = [[UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil] instantiateViewControllerWithIdentifier:@"ViewController"];

Dieser Link enthält Code zum Initiieren des Viewcontrollers im selben Storyboard

/*
 Helper to Switch the View based on StoryBoard
 @param StoryBoard ID  as String
*/
func switchToViewController(identifier: String) {
    let viewController = self.storyboard?.instantiateViewControllerWithIdentifier(identifier) as! UIViewController
    self.navigationController?.setViewControllers([viewController], animated: false)

}
Abhijeet
quelle
15

akashivskyys Antwort funktioniert gut! Falls Sie jedoch Probleme haben, vom vorgestellten Ansichts-Controller zurückzukehren, kann diese Alternative hilfreich sein. Es hat bei mir funktioniert!

Schnell:

let storyboard = UIStoryboard(name: "MyStoryboardName", bundle: nil)
let vc = storyboard.instantiateViewControllerWithIdentifier("someViewController") as! UIViewController
// Alternative way to present the new view controller
self.navigationController?.showViewController(vc, sender: nil)

Obj-C:

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MyStoryboardName" bundle:nil];
UIViewController *vc = [storyboard instantiateViewControllerWithIdentifier:@"someViewController"];
[self.navigationController showViewController:vc sender:nil];
Nahuel Roldan
quelle
12

Swift 4.2 aktualisierter Code ist

let storyboard = UIStoryboard(name: "StoryboardNameHere", bundle: nil)
let controller = storyboard.instantiateViewController(withIdentifier: "ViewControllerNameHere")
self.present(controller, animated: true, completion: nil)
Shahzaib Maqbool
quelle
7
// "Main" is name of .storybord file "
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
// "MiniGameView" is the ID given to the ViewController in the interfacebuilder
// MiniGameViewController is the CLASS name of the ViewController.swift file acosiated to the ViewController
var setViewController = mainStoryboard.instantiateViewControllerWithIdentifier("MiniGameView") as MiniGameViewController
var rootViewController = self.window!.rootViewController
rootViewController?.presentViewController(setViewController, animated: false, completion: nil)

Dies funktionierte gut für mich, als ich es in AppDelegate legte

Maxxafari
quelle
7

Wenn Sie es modal präsentieren möchten, sollten Sie so etwas wie unten haben:

let vc = self.storyboard!.instantiateViewControllerWithIdentifier("YourViewControllerID")
self.showDetailViewController(vc as! YourViewControllerClassName, sender: self)
Hamid
quelle
5

Ich möchte einen viel saubereren Weg vorschlagen. Dies ist nützlich, wenn wir mehrere Storyboards haben

1.Erstellen Sie eine Struktur mit all Ihren Storyboards

struct Storyboard {
      static let main = "Main"
      static let login = "login"
      static let profile = "profile" 
      static let home = "home"
    }

2. Erstellen Sie eine solche UIStoryboard-Erweiterung

extension UIStoryboard {
  @nonobjc class var main: UIStoryboard {
    return UIStoryboard(name: Storyboard.main, bundle: nil)
  }
  @nonobjc class var journey: UIStoryboard {
    return UIStoryboard(name: Storyboard.login, bundle: nil)
  }
  @nonobjc class var quiz: UIStoryboard {
    return UIStoryboard(name: Storyboard.profile, bundle: nil)
  }
  @nonobjc class var home: UIStoryboard {
    return UIStoryboard(name: Storyboard.home, bundle: nil)
  }
}

Geben Sie die Storyboard-ID als Klassennamen an und verwenden Sie den folgenden Code zum Instanziieren

let loginVc = UIStoryboard.login.instantiateViewController(withIdentifier: "\(LoginViewController.self)") as! LoginViewController
vijeesh
quelle
Wofür ist @nonobjc?
StackRunner
1
@StackRunner dies wird nicht für Ziel c
XcodeNOOB
3

Swift 4:

    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    let yourVC: YourVC = storyboard.instantiateViewController(withIdentifier: "YourVC") as! YourVC
zeichnete ..
quelle
2

Wenn Sie einen Viewcontroller haben, der kein Storyboard / Xib verwendet, können Sie wie folgt auf diese bestimmte VC zugreifen:

 let vcInstance : UIViewController   = yourViewController()
 self.present(vcInstance, animated: true, completion: nil)
Aks
quelle
Ich verstehe Folgendes: "Kann nicht erstellt werden, da keine zugänglichen Initialisierer vorhanden sind".
Paul Bénéteau
Die Outlets und andere Beziehungen, die vom Storyboard hergestellt werden, gehen verloren
jose920405
2

Swift 3 Storyboard

let settingStoryboard : UIStoryboard = UIStoryboard(name: "SettingViewController", bundle: nil)
let settingVC = settingStoryboard.instantiateViewController(withIdentifier: "SettingViewController") as! SettingViewController
self.present(settingVC, animated: true, completion: {

})
Giang
quelle
1

Ich weiß, dass es sich um einen alten Thread handelt, aber ich denke, dass die aktuelle Lösung (unter Verwendung einer fest codierten Zeichenfolgen-ID für einen bestimmten Ansichts-Controller) sehr fehleranfällig ist.

Ich habe ein Build-Time-Skript erstellt (auf das Sie hier zugreifen können ), mit dem ein Compiler-sicherer Weg für den Zugriff auf und die Instanziierung von View-Controllern von allen Storyboards innerhalb des angegebenen Projekts geschaffen wird.

Beispielsweise wird der Ansichtscontroller mit dem Namen vc1 in Main.storyboard wie folgt instanziiert:

let vc: UIViewController = R.storyboard.Main.vc1^  // where the '^' character initialize the controller
Nadav96
quelle
1

Egal was ich versucht habe, es würde einfach nicht für mich funktionieren - keine Fehler, aber auch kein neuer View Controller auf meinem Bildschirm. Ich weiß nicht warum, aber das Einwickeln in die Timeout-Funktion hat es endlich geschafft:

DispatchQueue.main.asyncAfter(deadline: .now() + 0.0) {
    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    let controller = storyboard.instantiateViewController(withIdentifier: "TabletViewController")
    self.present(controller, animated: true, completion: nil)
}
Starwave
quelle
1

Swift 5

let vc = self.storyboard!.instantiateViewController(withIdentifier: "CVIdentifier")
self.present(vc, animated: true, completion: nil)
Binoy Jose
quelle
0

Ich habe eine Bibliothek erstellt, die dies mit besserer Syntax viel einfacher handhabt:

https://github.com/Jasperav/Storyboardable

Ändern Sie einfach Storyboard.swift und lassen Sie das ViewControllersanpassen Storyboardable.

J. Doe
quelle