Programlı bir segue oluşturma


202

Eğer sıradan bir var UIViewControllerbenim tüm bu UIViewsControllersbazı ortak operasyonları yeniden uzatın.

Ben bu "Ortak" bir segue kurmak istiyorum UIViewControllerböylece tüm diğer UIViewControllersmiras.

Bunu programlı olarak nasıl yapacağımı anlamaya çalışıyorum.

Sanırım soru , hikaye panosuna girmeden ve bunları elle yapmadan segueherkes için nasıl ayarlayabilirim de olabilir UIViewControllers.

Yanıtlar:


169

Tanım gereği bir segue bir storyboard'dan bağımsız olarak var olamaz. Bu sınıfı adına bile var: UIStoryboardSegue. Programlı olarak sekmeler oluşturmazsınız - bunları sizin için oluşturan storyboard çalışma zamanıdır. Normalde performSegueWithIdentifier:görünüm denetleyicinizin kodunu arayabilirsiniz , ancak bu, referans için film şeridinde önceden ayarlanmış bir segue olmasına dayanır.

Sorduğum şey, ortak görünüm denetleyicinizde (temel sınıf) yeni bir görünüm denetleyicisine geçecek ve türetilmiş tüm sınıflar tarafından devralınacak bir yöntem nasıl oluşturabileceğinizdir. Temel sınıf görünüm denetleyicinize böyle bir yöntem oluşturarak bunu yapabilirsiniz:

- (IBAction)pushMyNewViewController
{
    MyNewViewController *myNewVC = [[MyNewViewController alloc] init];

    // do any setup you need for myNewVC

    [self presentModalViewController:myNewVC animated:YES];
}

ve sonra türetilmiş sınıfınızda, uygun düğme tıklatıldığında veya tablo satırı seçiliyse ya da her neyse bu yöntemi çağırın.


4
Teşekkürler. Programlı olarak yapamayacağımız bir utanç. Kaynak kodun kalitesini gerçekten artıracaktır (daha az çoğaltma her zaman iyidir). Önerinizle birlikte gideceğim.
Tiago Veloso

2
@jonkroll anahtar deyiminden segue çağırmak / gerçekleştirmek mümkün mü yani sahip olduğum indeks dayalı?
codejunkie

5
@codejunkie: Evet, bunu yapabilirsiniz. Bunun için UIViewControlleradlandırılmış yöntemi kullanırsınız performSegueWithIdentifier:sender:.
jonkroll

2
Programlı olarak segue oluşturma ve gerçekleştirme (cevabıma bakın). Kodumla ilgili yanlış bir şey varsa, cevabınız doğru ise?
Jean-Philippe Pellet

14
İOS 6+ için güncelleme: UIView's presentModalViewController:animated:kullanımdan kaldırıldı. Gönderen docs - (. İOS 6.0 Kullanım presentViewController kaldırılan özellikler: animasyonlu: tamamlama:. Yerine)
kullanıcı

346

Başka bir olasılık ekleyeceğimi düşündüm. Yapabileceğiniz şeylerden biri, bir eyleme bağlı olmayan bir segue kullanarak bir film şeridindeki iki sahneyi bağlayabilir ve daha sonra selamı görünüm denetleyicinizin içinde programlı olarak tetikleyebilirsiniz. Bunu yapmanın yolu, film şeridi sahnesinin altındaki segman sahnesinin altındaki dosyanın sahip simgesinden sürüklemeniz ve hedef sahneye sağ sürüklemenizdir. Açıklamak için bir görüntü atacağım.

resim açıklamasını buraya girin

"Manuel Segue" için bir açılır pencere görüntülenir. Tür olarak Push'u seçtim. Küçük kareye dokunun ve nitelik denetçisinde olduğunuzdan emin olun. Kodda başvurmak için kullanacağınız bir tanımlayıcı verin.

resim açıklamasını buraya girin

Tamam, şimdi programlı bir çubuk düğmesi öğesi kullanacağım. ViewDidLoad veya başka bir yerde gezinme çubuğunda şu kodla bir düğme öğesi oluşturacağım:

UIBarButtonItem *buttonizeButton = [[UIBarButtonItem alloc] initWithTitle:@"Buttonize"
                                                                    style:UIBarButtonItemStyleDone
                                                                   target:self
                                                                   action:@selector(buttonizeButtonTap:)];
self.navigationItem.rightBarButtonItems = @[buttonizeButton];

Tamam, seçicinin buttonizeButtonTap: olduğuna dikkat edin. Bu düğme için bir geçersiz yöntem yazın ve bu yöntem içinde segue'i şöyle çağırırsınız:

-(void)buttonizeButtonTap:(id)sender{
    [self performSegueWithIdentifier:@"Associate" sender:sender];
    }

PreparForSegue çağrıldığında düğmeyi tanımlamak için gönderen parametresi gerekir. preparForSegue, sahnenizi somutlaştıracağınız ve çalışmasını yapmak için ihtiyaç duyacağı değerleri ileteceğiniz çerçeve yöntemidir. İşte benim yöntem şöyle görünüyor:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if ([[segue identifier] isEqualToString:@"Associate"])
    {
        TranslationQuizAssociateVC *translationQuizAssociateVC = [segue destinationViewController];
        translationQuizAssociateVC.nodeID = self.nodeID; //--pass nodeID from ViewNodeViewController
        translationQuizAssociateVC.contentID = self.contentID;
        translationQuizAssociateVC.index = self.index;
        translationQuizAssociateVC.content = self.content;
    }
}

Tamam, sadece test ettim ve işe yarıyor. Umarım size yardımcı olur.


@MichaelRowe segue ihtiyacını nasıl ortadan kaldırıyor? Gördüğüm gibi hala Storyboard üzerinde hedef denetleyicisine sürükleyip bırakmanız gerekiyor ..
aherrick

@MichaelRowe bu segue ihtiyacını ortadan kaldırmaz. Bunun yaptığı, arayüz oluşturucu yerine kodda yerleşik olarak bulunan görünüm denetleyicileri arasında arama yapmanıza izin vermektir.
Matthew

@Matt aslında sadece benim app nasıl tamamen yeniden düşünmek gitmek gitmek ... Tüm UI tam bir yeniden yazma sonra artık segues kullanmıyorum ..
Michael Rowe

@cocoanut "Uygulama modally bir aktif denetleyici sunmaya çalıştı" bu konuda herhangi bir yardım olarak hata alıyorum ..
Bala

1
Manual Segue "Push" kullanımdan kaldırıldı, "Show" kullanın. Bu cevabın daha fazla detayı var. @smileBot lütfen cevabı güncelleyin.
NAbbas

81

Özel segue alt sınıfımı örneklemek ve programlı olarak çalıştırmak için bu kodu kullanıyorum. İşe yarıyor gibi görünüyor. Bunda yanlış bir şey mi var? Şaşkınım, diğer cevapları okuyamayacağımı söyleyerek okuyorum.

UIViewController *toViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"OtherViewControllerId"];
MyCustomSegue *segue = [[MyCustomSegue alloc] initWithIdentifier:@"" source:self destination:toViewController];
[self prepareForSegue:segue sender:sender];
[segue perform];

4
MyCustomSegue'de neler var?
Victor Engel

3
Bu özel bir alt sınıftır UIStoryboardSegue.
Jean-Philippe Pellet

7
@MarkAmery Birçok kişi (ben dahil) film şeridi kullanmaktan kaçınır. Birleştirilmesi zor ve geçmekte olduğum kimliğin performSegueWithIdentifier:film şeridinde gerçekten tanımlanmış olduğundan emin olmak için derleme zamanı kontrolü yok . Segue'i kendim yaratırsam tüm sorunlardan kaçınırım.
Jean-Philippe Pellet

3
Jean-Philippe'e katılıyorum. Film şeridini yönetmek popodaki bir acıdır. Tabii ki birkaç görünüm oluşturmak ve buraya bir segue ekleyerek bir segue ekleyerek yolunuzu tıklamak kolaydır, ancak üç geliştiriciniz varsa, korkunç bir şey olduğunda, XML'de tanımlanan 16 segue ile 6 görünüm yönetmek. Her neyse, nokta: kod size kontrol verir, xcode tarafından oluşturulan xml vermez.
Krystian

3
İOS7'de [segue perform] 'de bir kilitlenme görüyorum, başka birinin bunu deneyimlediğinden emin değilim.
Eric Chen

45

Sanırım bu cevaplandı ve kabul edildi, ama ben sadece birkaç ayrıntı daha eklemek istiyorum.

İlk ekran olarak bir giriş görünümü sunacağım ve daha sonra giriş doğru olsaydı uygulamaya bakmak istedim bir sorunu çözmek için ne yaptım. Oturum açma görünümü denetleyicisinden kök görünüm denetleyicisine segue oluşturdum ve "myidentifier" gibi bir tanımlayıcı verdim.

Sonra tüm giriş kodunu kontrol ettikten sonra giriş doğruysa

[self performSegueWithIdentifier: @"myidentifier" sender: self];

En büyük yanlış anlama, segue'i bir düğmeye koymaya çalıştığım ve bir kez bulunduğunda segue'i kesmeye çalışmamdı.


4
Başka bir yorum olarak yazdığım gibi: Programlı olarak özel segueler oluşturup gerçekleştiriyorum (cevabımı görün).
Jean-Philippe Pellet

32

Kodunuzu kullandığınız kodla ilişkilendirmeniz gerekir UIStoryboard. Emin gitmek olun YourViewController Gözlerinde farklı UIStoryboard, etrafındaki sınırında tıklatın ve sonra da set identifierbir alanını NSStringkodunuzda dediğimiz.

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" 
                                                     bundle:nil];
YourViewController *yourViewController = 
 (YourViewController *)
  [storyboard instantiateViewControllerWithIdentifier:@"yourViewControllerID"];
[self.navigationController pushViewController:yourViewController animated:YES];

1
Bunu anlıyorum, ama sunmak istediğim viewController film şeridinde bir NavigationController gömülü ise? Ne bulabilirim, içine gömmek için bir NavigationController başlatabilirim ama film şeridi, zaten sunulması gereken görünüm için itme segues kurulum var.
jhilgert00

1
bu konuyu biraz açıklayabilir misin? Bu yaşadığım sorun olduğunu düşünüyorum, ama t nasıl / nerede bunu bulmak için görünmüyor ...
jesses.co.tt

1
Bu çözüm bile doğru bir çözüm, Herhangi bir segueden kaçınmakla ilgili, ama soru segue ile ilgili. Bu şekilde, görsel senaryo taslaklarında segue OLMADAN iki sahne arasında bağlantı kurabilir veya geçiş yapabilirsiniz.
BootMaker

16

Film şeridindeki denetleyiciler için.

jhilgert00 aradığınız bu mu?

-(IBAction)nav_goHome:(id)sender {
UIViewController *myController = [self.storyboard instantiateViewControllerWithIdentifier:@"HomeController"];
[self.navigationController pushViewController: myController animated:YES];

}

VEYA...

[self performSegueWithIdentifier:@"loginMainSegue" sender:self];


3

Bir açıklama eklemek istiyorum ...

Yaygın bir yanlış anlama, aslında bir süredir yaşadığım bir, bir storyboard segueinin prepareForSegue:sender:yöntemle tetiklenmesidir . O değil. Bir storyboard segue, prepareForSegue:sender:bu (denetleyiciden çıkış) görünüm denetleyicisi için bir yöntem uygulayıp uygulamadığınıza bakılmaksızın gerçekleştirilecektir .

Bunu Paul Hegarty'ın mükemmel iTunesU derslerinden öğrendim . Özür dilerim ama maalesef hangi dersi hatırlayamıyorum.

Bir film şeridindeki iki görünüm denetleyicisi arasında bir segue bağlarsanız, ancak prepareForSegue:sender: yöntem segue yine de hedef görünüm denetleyicisine segue olur. Ancak, bu görünüm denetleyicisinin hazırlıksız olmasını isteyecektir.

Bu yardımcı olur umarım.


3

Storyboard Segues, storyboard dışında oluşturulamaz. Dezavantajlarına rağmen kablolamanız gerekir.

UIStoryboardSegue Reference açıkça şunları belirtir:

Doğrudan segue nesneleri oluşturmazsınız. Bunun yerine, film şeridi çalışma zamanı, bunları iki görünüm denetleyicisi arasında bir segue gerçekleştirmesi gerektiğinde oluşturur. İsterseniz UIViewController performSegueWithIdentifier: sender: yöntemini kullanarak programlı olarak bir segue başlatabilirsiniz. Programlı olarak eklenen ve bu nedenle Arayüz Oluşturucu'da bulunmayan bir kaynaktan bir segue başlatmak için bunu yapabilirsiniz.

Yine de programlı olarak film şeridine segue kullanarak presentModalViewController:veya pushViewController:animated:aramaları kullanarak bir görünüm denetleyicisi sunmasını söyleyebilirsiniz , ancak bir storyboard örneğine ihtiyacınız olacaktır.

UIStoryboardAna paket için paket nil ile adlandırılmış bir storyboard almak için s class yöntemini çağırabilirsiniz .

storyboardWithName:bundle:


2

İlk olarak, film şeridinde iki farklı görünümünüz olduğunu ve bir ekrandan diğerine gitmek istediğinizi varsayalım, bu nedenle aşağıdaki adımları izleyin:

1). Tüm dosyalarınızı sınıf dosyası ve kimlik denetçisinde film şeridi kimliği ile tanımlayın.

2). İlk görünüme bir gezinti denetleyicisi eklediğinizden emin olun. Film Şeridi'nden seçin ve ardından Editör> Yerleştir> Gezinti Denetleyici

3). Birinci sınıfınızda "secondClass.h" dosyasını içe aktarın

#import "ViewController.h
#import "secondController.h"

4). Bu komutu segue gerçekleştirmek zorunda olan IBAction'a ekleyin

secondController *next=[self.storyboard instantiateViewControllerWithIdentifier:@"second"];
[self.navigationController pushViewController:next animated:YES];

5). @"second"secondview denetleyici sınıfı, film şeridi kimliği.


self.storyboardolmalı:UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
masipcat

@masipcat ve Öykü panosu adı, Xcode projenizi nasıl ayarladığınıza bağlı olabilir, benimkinde "Main.storyboard" idi, bu yüzden kullandımstoryboardWithName:@"Main"
ammianus

@ sanket-chauhan ilk kontrol cihazınız bir Navigasyon Kontrolörüne yerleştirilmemişse, [self showDetailViewController:next sender:self];veya[self showViewController:next sender:self];
amianus ile

1

UIStoryboard'un sekmelerinin tersine mühendislikini yaptım ve açık kaynaklı (yeniden) bir uygulama yaptım: https://github.com/acoomans/Segway

Bu kütüphane ile segileri programlı olarak tanımlayabilirsiniz (herhangi bir storyboard olmadan).

Umarım yardımcı olabilir.


0

Aslında birkaç sorun var:

İlk olarak, bizim için yüklediğiniz projede, segue "segue1" tanımlayıcısını taşımaz:

tanımlayıcı yok

Henüz yapmadıysanız bu tanımlayıcıyı doldurmalısınız.

İkinci olarak, tablo görünümünden tablo görünümüne geçerken, bir görünüm denetleyicisi oluşturmak için initWithNibName öğesini çağırıyorsunuz. Gerçekten instantiateViewControllerWithIdentifier kullanmak istiyorsunuz.


0

İşte kod örneği Creating a segue programmatically:

class ViewController: UIViewController {
    ...
    // 1. Define the Segue
    private var commonSegue: UIStoryboardSegue!
    ...
    override func viewDidLoad() {
        ...
        // 2. Initialize the Segue
        self.commonSegue = UIStoryboardSegue(identifier: "CommonSegue", source: ..., destination: ...) {
            self.commonSegue.source.showDetailViewController(self.commonSegue.destination, sender: self)
        }
        ...
    }
    ...
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        // 4. Prepare to perform the Segue
        if self.commonSegue == segue {
            ...
        }
        ...
    }
    ...
    func actionFunction() {
        // 3. Perform the Segue
        self.prepare(for: self.commonSegue, sender: self)
        self.commonSegue.perform()
    }
    ...
}

self.prepare(for: self.commonSegue, sender: self)Eylem yönteminizden çağırıyorsunuz . Sonra karşılaştırarak ne anlamı var if self.commonSegue == segue {...}içinde prepare(for:sender)yöntemle?
nayem

@nayem: prepare(for:sender:)Hedef görüntüleme denetleyicisini görüntülenmeden önce yapılandırabilirsiniz. Tabii ki de yapabilirsiniz actionFunction.
jqgsninimo

@nayem: Bunu yapmamın nedeni, diğer sekmelerin işlenmesi ile tutarlı olmaya çalışmak.
jqgsninimo
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.