Swift'te bir viewController'ı örnekleme ve sunma


300

Konu

Yeni bir görünüm almaya başladı Swifttarihinde adlı Xcode 6ve bazı demo proje ve öğreticiler çalıştı. Şimdi şurada takıldım:

viewControllerBelirli bir film şeridinden örnek oluşturma ve ardından sunma

Objective-C Çözümü

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

Swift'te bunu nasıl başarabilirim?

Yanıtlar:


648

Bu yanıt en son Swift 5.2 ve iOS 13.4 SDK için revize edildi.


Her şey yeni bir sözdizimi ve biraz revize edilmiş API'lar meselesi. UIKit'in temel işlevselliği değişmedi. Bu, iOS SDK çerçevelerinin büyük çoğunluğu için geçerlidir.

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

Sorun yaşıyorsanız init(coder:), lütfen EridB'nin cevabına bakın .


3
Hatta atlayabilirsiniz ;! ;) Üzerinde durmayı düşünür müsünüz as UIViewController? Bu neden gerekli?
Sebastian Wramba

5
asanahtar kelime yazma için kullanılır. (UIViewController *)anObjectObjektif c ile aynı
Garoal

1
Evet, onları atlayabileceğimi biliyorum ama bu uzun alışkanlığın bir parçası. : D olarak instantiateViewControllerWithIdentifierdöner AnyObject( idSwift eşdeğer) ve beyan vcolarak UIViewControllerbir typecasting zorunda AnyObjectiçin UIViewController.
akashivskyy

Merhaba arkadaşlar, ben farklı bir sorunla karşı karşıyayım, Bu kod simülatörde iOS v7.1.2'ye sahip olan ipad2'de çalışmıyor. Eğer sakıncası yoksa bu sorunu çözmeme yardım et.
Indra

3
@akashivskyy Kesinlikle, sana. Ama belki bazıları için değil.
mmc

43

@ Akashivskyy'nin somutlaştırmak için cevabını kullanan UIViewControllerve istisnası olan insanlar için:

ölümcül hata: sınıf için uygulanmamış başlatıcı 'init (coder :)' kullanımı

Hızlı ipucu:

required init?(coder aDecoder: NSCoder)Hedefinize UIViewController, somutlaştırmaya çalıştığınız el ile uygulayın

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

Daha fazla açıklamaya ihtiyacınız varsa lütfen cevabımı buraya bakın


Özel başlatıcı kullanmak istiyorsanız, super.init (nibName: nil, bundle: nil) ile super'i çağırabilirsiniz ve whew iyi yüklenir veya NIB dosyasının adıyla çağırabilir.
user1700737

4
@ user1700737 initWithCoder değil, initWithCoder yürüten film şeridine atıfta bulunan viewController uygulamasını başlatıyorum. Bu soruya bakın stackoverflow.com/questions/24036393/…
E-Riddie

Merhaba arkadaşlar, ben farklı bir sorunla karşı karşıyayım, Bu kod simülatörde iOS v7.1.2'ye sahip olan ipad2'de çalışmıyor. Eğer sakıncası yoksa bu sorunu çözmeme yardım et.
Indra

@Indra yığın hakkında başka bir soru sormanız gerekiyor, bana bağlantı verin Size yardımcı olmaktan mutluluk duyarım!
E-Riddie

Swift 1.2'de init(coder aDecoder: NSCoder!)"gerekli" yapmalısınız . Şimdi aşağıdakileri yazmalısınız:required init(coder aDecoder: NSCoder!)
Eduardo Viegas

18

Bu bağlantının her iki uygulaması da vardır:

Swift:

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

Hedef C

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

Bu bağlantı, aynı film şeridinde viewcontroller'ı başlatmak için kod içeriyor

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

akashivskyy'nin cevabı gayet iyi çalışıyor! Ancak, sunulan görünüm denetleyicisinden dönen bir sorunla karşılaşırsanız, bu alternatif yardımcı olabilir. Benim için çalıştı!

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

12

Swift 4.2 güncellenmiş kodu

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)

AppDelegate'e koyduğumda bu benim için iyi çalıştı


7

Modal bir şekilde sunmak istiyorsanız, aşağıdaki gibi bir şeye sahip olmalısınız:

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

5

Çok daha temiz bir yol önermek istiyorum. Birden fazla film şeridimiz olduğunda bu yararlı olacaktır

Tüm hikaye tahtalarınızla bir yapı oluşturun

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

2. Bunun gibi bir UIStoryboard uzantısı oluşturun

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

Film şeridi tanımlayıcısını sınıf adı olarak verin ve örneklemek için aşağıdaki kodu kullanın

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

@Nonobjc ne için?
StackRunner

1
@StackRunner bu objektif c için geçerli olmayacak
XcodeNOOB

3

Hızlı 4:

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

2

Herhangi bir storyboard / Xib kullanmayan bir Viewcontroller'ınız varsa, bu çağrıya aşağıdaki gibi çağrı yapabilirsiniz:

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

Bunu alıyorum: "erişilebilir başlatıcısı olmadığı için inşa edilemez".
Paul Bénéteau

film şeridi tarafından yapılan çıkışlar ve diğer ilişkiler kaybedildi
jose920405

2

Hızlı 3 Film Şeridi

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

})

1

Ben eski bir iş parçacığı biliyorum, ama geçerli çözüm (verilen görünüm denetleyicisi için sabit kodlu dize tanımlayıcısı kullanarak) çok hatalara eğilimli olduğunu düşünüyorum.

Verilen projedeki tüm film şeridinden görünüm denetleyicilerine erişmek ve örnek oluşturmak için derleyici güvenli bir yol oluşturacak bir derleme zamanı komut dosyası ( buraya erişebilirsiniz ) oluşturdum.

Örneğin, görünüm denetleyicisi adlı VC1 içinde Main.storyboard şöyle örneği olacak:

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

1

Ne denediğim önemli değil, sadece benim için işe yaramaz - hata yok, ama ekranımda yeni bir görünüm denetleyicisi yok. Nedenini bilmiyorum, ama zaman aşımı işlevine sarmak nihayet işe yaradı:

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

Hızlı 5

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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.