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?

E-Riddie
sumber

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 .

akashivskyy
sumber
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

E-Riddie
sumber
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)

}
Abhijeet
sumber
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];
Nahuel Roldan
sumber
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)
Shahzaib Maqbool
sumber
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

Maxxafari
sumber
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)
Hamid
sumber
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
vijeesh
sumber
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
menggambar ..
sumber
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)
Aks
sumber
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: {

})
Giang
sumber
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
Nadav96
sumber
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)
}
Starwave
sumber
1

Cepat 5

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