Tworzenie instancji i prezentowanie kontrolera viewController w Swift

Wydanie

Zacząłem przeglądać nowe Swift na Xcode 6 i wypróbowałem kilka projektów demo i samouczków. Teraz utknąłem w:

Tworzenie instancji, a następnie prezentowanie viewController z określonego storyboardu

Objective-C Solution

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

Jak to osiągnąć na Swift?

Author: EridB, 2014-06-04

12 answers

To wszystko kwestia nowej składni, funkcjonalność się nie zmieniła:

// Swift 3.0

let storyboard = UIStoryboard(name: "MyStoryboardName", bundle: nil)
let controller = storyboard.instantiateViewController(withIdentifier: "someViewController")
self.present(controller, animated: true, completion: nil)

Jeśli masz problemy z init(coder:), zapoznaj się z odpowiedzią EridB.

 535
Author: akashivskyy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:54

Dla osób używających @ akashivskyy ' s answer do tworzenia instancji UIViewController i mają wyjątek:

Fatal error: use of unimplemented INIT(coder:) 'for class

Szybka wskazówka:

Ręcznie zaimplementuj required init?(coder aDecoder: NSCoder) w miejscu docelowym UIViewController, które próbujesz utworzyć

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

Jeśli potrzebujesz więcej opisu, zapoznaj się z moją odpowiedzią tutaj

 41
Author: EridB,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-13 13:02:56

Ten link ma obie implementacje:

Swift:

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

Objective C

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

Ten link zawiera kod do inicjowania viewcontroller w tym samym storyboardzie

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

}
 14
Author: Abhijeet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:47:29

Odpowiedź Akashivskyy działa dobrze! Ale jeśli masz problemy z powrotem z prezentowanego kontrolera widoku, ta alternatywa może być pomocna. U mnie zadziałało!

Swift:

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];
 10
Author: Nahuel Roldan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-07 18:29:47
// "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)

To działało dobrze dla mnie, gdy umieściłem go w AppDelegate

 6
Author: Maxxafari,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-08 17:17:49

Jeśli chcesz zaprezentować go modalnie, powinieneś mieć coś w stylu poniżej:

let vc = self.storyboard!.instantiateViewControllerWithIdentifier("YourViewControllerID")
self.showDetailViewController(vc as! YourViewControllerClassName, sender: self)
 5
Author: Hamid,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-26 20:41:01

Jeśli masz Viewcontroller nie używający żadnego storyboard / Xib, możesz wcisnąć ten VC jak poniżej wywołanie:

 let vcInstance : UIViewController   = yourViewController()
 self.present(vcInstance, animated: true, completion: nil)
 2
Author: Aks,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-14 20:19:07

Swift 4:

    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    let yourVC: YourVC = storyboard.instantiateViewController(withIdentifier: "YourVC") as! YourVC
 2
Author: drew..,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-18 19:36:13

Wiem, że to stary wątek, ale myślę, że obecne rozwiązanie (używając twardego identyfikatora łańcucha dla danego kontrolera widoku) jest bardzo podatne na błędy.

Stworzyłem skrypt czasu kompilacji (do którego można uzyskać dostęp tutaj ), który stworzy kompilator bezpieczny sposób dostępu i tworzenia instancji kontrolerów widoku ze wszystkich scenorysów w danym projekcie.

Na przykład kontroler widoku o nazwie vc1 W Main.storyboard będzie instancjonowany jak więc:

let vc: UIViewController = R.storyboard.Main.vc1^  // where the '^' character initialize the controller
 1
Author: Nadav96,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-25 19:17:25

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: {

})
 1
Author: Giang,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-13 03:39:42

Bez względu na to, co próbowałem, to po prostu nie działa dla mnie - żadnych błędów, ale nie nowy kontroler widoku na ekranie albo. Nie wiem dlaczego, ale owinięcie go w funkcję timeout w końcu sprawiło, że zadziałał:

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)
}
 1
Author: Starwave,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-08 11:58:23

Chciałbym zaproponować znacznie czystszy sposób. Będzie to przydatne, gdy mamy wiele storyboardów

1.Stwórz strukturę ze wszystkimi storyboardami

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

2. Utwórz rozszerzenie UIStoryboard w ten sposób

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

Podaj identyfikator storyboard jako nazwę klasy i użyj poniższego kodu, aby utworzyć instancję

let loginVc = UIStoryboard.login.instantiateViewController(withIdentifier: "\(LoginViewController.self)") as! LoginViewController
 0
Author: vijeesh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-13 11:14:10