Storyboard - AppDelegate'te ViewController'a bakın


122

Şu senaryoyu düşünün: Film şeridi tabanlı bir uygulamam var. Storyboard'a bir ViewController nesnesi ekliyorum, bu ViewController için sınıf dosyalarını projeye ekliyorum ve IB kimlik denetçisinde yeni sınıfın adını belirtiyorum. Şimdi bu ViewController'a AppDelegate'ten programlı olarak nasıl başvuracağım? İlgili sınıfla bir değişken oluşturdum ve onu bir IBOutlet özelliğine çevirdim, ancak kodda yeni ViewController'a başvurmanın herhangi bir yolunu görmüyorum - bir bağlantıyı ctrl-sürüklemeye yönelik herhangi bir girişim çalışmıyor .

Yani AppDelegate içinde temel ViewController'a bu şekilde ulaşabilirim

(MyViewController*) self.window.rootViewController

ama film şeridinde bulunan herhangi bir ViewController nasıl olur?


Bu yanıtı kontrol edin . Hızlıdır, ancak diller benzerdir.
Borzh

Yanıtlar:


165

Göz at belgelere için -[UIStoryboard instantiateViewControllerWithIdentifier:]. Bu, IB Attributes Inspector'da ayarladığınız tanımlayıcıyı kullanarak film şeridinizden bir görünüm denetleyicisi başlatmanıza olanak tanır:

görüntü açıklamasını buraya girin

Örnek kod eklemek için DÜZENLENDİ:

UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:@"MainStoryboard"
                                                         bundle: nil];

MyViewController *controller = (MyViewController*)[mainStoryboard 
                    instantiateViewControllerWithIdentifier: @"<Controller ID>"];

Merhaba Robin, bunun için teşekkürler! Bu belgeye baktım ama örnekleme ve başlatma sözcüklerini karıştırdım ... bu bizi oraya götürüyor (talimatınızı izledikten sonra :) (yanıtlarda kod biçimlendirme eksikliğine lanet olsun ...) UIStoryboard * mainStoryboard = [UIStoryboard storyboardWithName: @ "MainStoryboard" paketi: nil]; MyViewController * thisController = (MyViewController *) [mainStoryboard instantiateViewControllerWithIdentifier: @ "myvc"];
Matthias D

Örnek kodunuzu, buna bakan herkes için biçimlendirme ile yanıta ekledim.
Robin Summerhill

24
Evrensel bir uygulama yapıyorsanız MainStoryboard_iPhone / MainStoryboard_iPad'i kullandığınızdan emin olun, aksi takdirde bir kilitlenme yaşarsınız.
roocell

16
Temsilcinin içinden info.plist'iniz tarafından yüklenen storyboard örneğine şu şekilde erişebilirsiniz: [[[self window] rootViewController] storyboard] Dokümanlara göre bu, "görünüm denetleyicisinin geldiği film şeridi" ni döndürecektir. (veya bir film şeridinden gelmediyse sıfır ). Bu UIStoryboard'dan *, @RobinSummerhill'in bahsettiği çağrıları başlatabilirsiniz. Storyboard'ların, viewControllers'ınızın ( sahneler ) yeni örneklerini ihtiyaç duyuldukça somutlaştırdığını ve daha önce görüntülenenleri yeniden kullanmadığını unutmayın.
Tad Bumcrot

6
OP'nin ŞU ANDA ÇALIŞAN vc'YE NASIL GİDİLECEĞİNİ bilmek istediğine inanıyorum. Nasıl yükleneceğini değil. Tam olarak onun açıkladığı gibi, bu self.window.rootViewController'ı önceden söyleyebiliyordunuz ve şimdi artık söyleyemiyorsunuz .
Şişko

41

Eğer kullanırsanız XCode5 Eğer farklı bir şekilde yapmalı.

  • Senin seçin UIViewControllerinUIStoryboard
  • Git Identity Inspectorsağ üst bölmedeki
  • kontrol Use Storyboard IDkutusunu
  • Storyboard IDAlana benzersiz bir kimlik yazın

Ardından kodunuzu yazın.

// Override point for customization after application launch.

if (<your implementation>) {
    UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:@"Main" 
                                                             bundle: nil];
    YourViewController *yourController = (YourViewController *)[mainStoryboard 
      instantiateViewControllerWithIdentifier:@"YourViewControllerID"];
    self.window.rootViewController = yourController;
}

return YES;

4
Bildiğim ve deneyebildiğim kadarıyla, bu güncellenmiş cevap.
gnclmorais

Bir film şeridinin adı, uzantısız dosya adıdır, dolayısıyla projenizi bu şekilde oluşturduysanız "Main_iPhone" veya "Main_iPad" de olabilir.
Brian White

ve sonra oturum açtıktan sonra orijinal rootViewController'a nasıl geri döneceğiz. En azından iOS 7 ve Xcode 5.0.2 hakkındaki bilgilerime göre - kök görünüm denetleyicisini geri değiştirmek, anında ve animasyon olmadan görünüm hiyerarşisini değiştirir. UX ekibi kodlayıcıları daha ucuza öldürdü.
lol

Swift kullanarak bunu nasıl yapacağım?
Leo Dabus

8

Genel olarak, sistem bir storyboard ile görünüm denetleyicisi somutlaştırmasını işlemelidir. İstediğiniz şey, görsel senaryo taslağınızı doğru bir şekilde kurduysanız self.window.rootViewControllerzaten doğru şekilde başlatılmış olması gereken görünüm denetleyicileri başlatmanın aksine, bir referans alarak viewController hiyerarşisini geçmek .

Öyleyse, diyelim ki sizin rootViewControllerbir UINavigationController ve sonra onun üstten görünüm denetleyicisine bir şey göndermek istiyorsunuz, bunu AppDelegate'inizde şu şekilde yaparsınız didFinishLaunchingWithOptions:

UINavigationController *nav = (UINavigationController *) self.window.rootViewController;
MyViewController *myVC = (MyViewController *)nav.topViewController;
myVC.data = self.data;

Swift'de çok benzer olursa:

let nav = self.window.rootViewController as! UINavigationController;
let myVC = nav.topViewController as! MyViewController
myVc.data = self.data

Normal öykü panosunun yüklenme şeklini atlamak ve tüm film şeridini kendiniz yüklemek istemiyorsanız, uygulama temsilcisinden gelen film şeridi kimliklerini kullanarak görünüm denetleyicilerini gerçekten başlatmamalısınız. AppDelegate'den sahneleri başlatmak zorunda kalırsanız, büyük olasılıkla yanlış bir şeyler yapıyorsunuzdur. Demek istediğim, bir nedenden ötürü, yığının aşağısındaki bir görünüm denetleyicisine veri göndermek istediğinizi hayal edin, AppDelegate verileri ayarlamak için görünüm denetleyicisi yığınına ulaşmamalıdır. Bu onun işi değil. Bu iş, rootViewController'dir. Bırakın rootViewController kendi alt öğelerini yönetsin! Bu nedenle, sistem tarafından normal film şeridi yükleme işlemini info.plist dosyasındaki referansları kaldırarak atlasaydım, en çok rootViewController'ı kullanarak başlatırdım.instantiateViewControllerWithIdentifier:ve bir UINavigationController gibi bir konteyner ise muhtemelen köküdür. Kaçınmak istediğiniz şey, film şeridi tarafından halihazırda somutlaştırılmış olan görünüm denetleyicilerini somutlaştırmaktır. Bu çok gördüğüm bir problem. Kısacası, kabul edilen cevaba katılmıyorum. Aksi takdirde 2 film şeridi yükleyeceğinizden, posterler storyboard yüklemesini info.plist'ten kaldırmak anlamına gelmediği sürece yanlıştır, bu bir anlam ifade etmez. Muhtemelen bir bellek sızıntısı değildir çünkü sistem kök sahneyi başlattı ve onu pencereye atadı, ama sonra siz gelip onu yeniden başlattınız ve yeniden atadınız. Uygulamanız oldukça kötü bir başlangıç ​​yaptı!


0
    UIStoryboard * storyboard = [UIStoryboard storyboardWithName:@"Tutorial" bundle:nil];
    self.window.rootViewController = [storyboard instantiateInitialViewController];
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.