Instantiate dan Presentasikan viewController di Swift


300

Isu

Aku mulai mengambil melihat yang baru Swiftdi Xcode 6, dan aku mencoba beberapa proyek demo dan tutorial. Sekarang saya terjebak di:

Instantiating dan kemudian menyajikan viewControllerdari storyboard tertentu

Solusi Objektif-C

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

Bagaimana cara mencapai ini di Swift?

Jawaban:


648

Jawaban ini terakhir direvisi untuk Swift 5.2 dan iOS 13.4 SDK.


Ini semua masalah sintaksis baru dan API yang sedikit direvisi. Fungsionalitas yang mendasari UIKit belum berubah. Ini berlaku untuk sebagian besar kerangka kerja iOS SDK.

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

Jika Anda mengalami masalah dengan init(coder:), silakan merujuk ke jawaban EridB .


3
Anda bahkan dapat menghilangkan ;! ;) Apakah Anda keberatan menguraikan as UIViewController? Mengapa itu perlu?
Sebastian Wramba

5
askata kunci digunakan untuk typecasting. Sama seperti (UIViewController *)anObjectpada tujuan c
Garoal

1
Ya saya tahu saya bisa menghilangkannya tetapi itu adalah bagian dari kebiasaan panjang. : D Ketika instantiateViewControllerWithIdentifierkembali AnyObject( idsetara dengan Swift) dan saya menyatakan vcsebagai UIViewController, saya harus mengetikkan AnyObjectke UIViewController.
akashivskyy

Hai Teman-teman, saya menghadapi beberapa masalah berbeda, kode ini berjalan pada simulator bukan pada iPad2 saya yang memiliki iOS v7.1.2. Jika Anda tidak keberatan bantu saya untuk menyelesaikan masalah ini.
Indra

3
@akashivskyy Pasti, untuk Anda. Tapi mungkin tidak untuk beberapa orang.
mmc

43

Untuk orang yang menggunakan jawaban @ akashivskyy untuk instantiate UIViewControllerdan memiliki pengecualian:

kesalahan fatal: penggunaan inisialisasi initializer 'init (coder :)' yang tidak diterapkan untuk kelas

Kiat cepat:

Implementasikan secara manual required init?(coder aDecoder: NSCoder)di tujuan UIViewControllerAnda yang ingin Anda instantiate

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

Jika Anda membutuhkan deskripsi lebih lanjut, silakan merujuk ke jawaban saya di sini


Jika Anda ingin menggunakan penggagas kustom, Anda dapat memanggil super dengan super.init (nibName: nil, bundle: nil) dan hasilnya akan dimuat dengan baik atau panggil dengan nama file NIB.
user1700737

4
@ user1700737 Saya instantiating viewController merujuk ke storyboard, yang mengeksekusi initWithCoder, bukan initWithNib. Lihat pertanyaan ini stackoverflow.com/questions/24036393/…
E-Riddie

Hai Teman-teman, saya menghadapi beberapa masalah berbeda, kode ini berjalan pada simulator bukan pada iPad2 saya yang memiliki iOS v7.1.2. Jika Anda tidak keberatan bantu saya untuk menyelesaikan masalah ini.
Indra

@Indra Anda perlu bertanya pertanyaan lain tentang tumpukan, beri saya tautannya. Saya akan dengan senang hati membantu Anda!
E-Riddie

Pada Swift 1.2 Anda harus membuat init(coder aDecoder: NSCoder!)"wajib". Jadi sekarang Anda harus menulis yang berikut ini:required init(coder aDecoder: NSCoder!)
Eduardo Viegas

18

Tautan ini memiliki kedua implementasinya:

Cepat:

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

Tujuan C

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

Tautan ini memiliki kode untuk memulai viewcontroller di storyboard yang sama

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

}

15

Jawaban akashivskyy bekerja dengan baik! Tetapi, jika Anda mengalami kesulitan untuk kembali dari pengontrol tampilan yang disajikan, alternatif ini dapat membantu. Itu berhasil untuk saya!

Cepat:

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];

12

Kode Swift 4.2 yang diperbarui adalah

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

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)

Ini bekerja dengan baik untuk saya ketika saya menaruhnya di AppDelegate


7

Jika Anda ingin menyajikannya secara modern, Anda harus memiliki sesuatu seperti di bawah ini:

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

5

Saya ingin menyarankan cara yang jauh lebih bersih. Ini akan berguna ketika kita memiliki banyak storyboard

1. Buat struktur dengan semua storyboard Anda

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

2. Buat ekstensi UIStoryboard seperti ini

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

Berikan pengenal papan cerita sebagai nama kelas, dan gunakan kode di bawah ini untuk instantiate

let loginVc = UIStoryboard.login.instantiateViewController(withIdentifier: "\(LoginViewController.self)") as! LoginViewController

Untuk apa @ nonobjc?
StackRunner

1
@StackRunner ini tidak akan tersedia untuk tujuan c
XcodeNOOB

3

Swift 4:

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

2

Jika Anda memiliki Viewcontroller yang tidak menggunakan storyboard / Xib, Anda dapat mendorong ke VC khusus ini seperti panggilan di bawah ini:

 let vcInstance : UIViewController   = yourViewController()
 self.present(vcInstance, animated: true, completion: nil)

Saya mendapatkan ini: "tidak dapat dibangun karena tidak memiliki inisialisasi yang dapat diakses".
Paul Bénéteau

outlet dan hubungan lain yang dibuat oleh storyboard hilang
jose920405

2

Cepat 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

Saya tahu ini adalah thread lama, tapi saya pikir solusi saat ini (menggunakan pengidentifikasi string hardcoded untuk tampilan controller yang diberikan) sangat rentan terhadap kesalahan.

Saya telah membuat skrip waktu pembuatan (yang dapat Anda akses di sini ), yang akan membuat cara kompiler aman untuk mengakses dan membuat instance pengendali tampilan dari semua storyboard dalam proyek yang diberikan.

Sebagai contoh, lihat kontroler bernama VC1 di Main.storyboard akan dipakai seperti:

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

1

Tidak peduli apa yang saya coba, itu tidak akan berhasil untuk saya - tidak ada kesalahan, tetapi tidak ada pengontrol tampilan baru di layar saya juga. Tidak tahu mengapa, tetapi membungkusnya dalam fungsi batas waktu akhirnya membuatnya berfungsi:

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

Cepat 5

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

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.