プログラムでセグエを作成する


202

私はUIViewControllerすべての私のUIViewsControllers、いくつかの一般的な操作を再利用するために拡張します。

UIViewController他のすべてがUIViewControllers継承できるように、この「共通」にセグエを設定したいと思います。

プログラムでそれを行う方法を理解しようとしています。

問題は、ストーリーボードに行かずsegueにすべてを自分で設定UIViewControllersし、手動で行う方法でもあると思います。

回答:


169

定義上、セグエはストーリーボードとは別に存在することはできません。クラスの名前にも含まれています:UIStoryboardSegue。プログラムでセグエを作成するのではなく、セグエを作成するのはストーリーボードランタイムです。通常performSegueWithIdentifier:、ビューコントローラーのコードで呼び出すことができますが、これは、参照するためにストーリーボードにセグエが既に設定されていることに依存しています。

新しいビューコントローラーに移行し、すべての派生クラスによって継承される、共通のビューコントローラー(基本クラス)でメソッドを作成する方法について、私はあなたが尋ねていると思います。これを行うには、基本クラスのビューコントローラーに次のようなメソッドを作成します。

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

    // do any setup you need for myNewVC

    [self presentModalViewController:myNewVC animated:YES];
}

次に、派生クラスで、適切なボタンがクリックされたとき、またはテーブルの行が選択されたときに、そのメソッドを呼び出します。


4
ありがとう。プログラムで実行できないのは残念です。それは本当にソースコードの品質を向上させます(重複を少なくすることは常に良いことです)。私はあなたの提案を試してみるつもりです。
Tiago Veloso

2
@jonkrollは、switchステートメントからセグエを呼び出す/実行することは可能ですか?つまり、私が持っているインデックスに基づいていますか?
codejunkie

5
@codejunkie:はい、できます。このためにUIViewController指定さperformSegueWithIdentifier:sender:れたメソッドを使用します。
jonkroll 2012

2
私はプログラムでセグエを作成して実行しています(私の回答を参照)。あなたの答えが正しいなら、私のコードに何か問題がありますか?
Jean-Philippe Pellet 2013年

13
iOS版6+の更新:UIViewさんがpresentModalViewController:animated:推奨されていません。ドキュメントから- (iOS 6.0では非推奨。代わりにpresentViewController:animated:completion:を使用してください。)
ユーザー

346

私は別の可能性を追加すると思いました。実行できることの1つは、アクションに接続されていないセグエを使用してストーリーボードの2つのシーンを接続し、ビューコントローラー内でプログラム的にセグエをトリガーすることです。これを行う方法は、ストーリーボードシーンの下部にあるファイルの所有者アイコンから、別のシーンであるシーンをドラッグして、目的のシーンに右ドラッグする必要があることです。説明に役立つように画像を入れます。

ここに画像の説明を入力してください

「Manual Segue」のポップアップが表示されます。タイプとしてプッシュを選択しました。小さな正方形をタップして、属性インスペクターにいることを確認してください。コードで参照するために使用する識別子を指定します。

ここに画像の説明を入力してください

では、プログラムによるバーボタンアイテムを使用してセグエを作成します。viewDidLoadまたはその他の場所で、次のコードを使用してナビゲーションバーにボタン項目を作成します。

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

OK、セレクターがbuttonizeButtonTap:であることに注意してください。そのボタンのvoidメソッドを記述し、そのメソッド内で次のようにセグエを呼び出します。

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

prepareForSegueが呼び出されたときにボタンを識別するには、senderパラメーターが必要です。prepareForSegueは、シーンをインスタンス化し、作業に必要な値を渡すフレームワークメソッドです。私のメソッドは次のようになります:

- (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;
    }
}

OK、テストしただけで動作します。お役に立てば幸いです。


@MichaelRoweこれはどのようにしてセグエの必要性を排除しますか?私はそれを参照してくださいとして、あなたはまだ先のコントローラにストーリーボードにドラッグアンドドロップする。..持っている
aherrick

@MichaelRoweこれはセグエの必要性を排除しません。これにより、インターフェイスビルダーではなくコードに組み込まれているビューコントローラー間を移動できます。
マシュー14

@Mattは、それは実際にちょうど私は完全に私はセットアップ私のアプリは...すべてのUI Iを完全に書き直した後、もはや..いかなるseguesを使用しない方法を再考行く
マイケル・ロウ

この..に関するいかなる助けを「アプリケーションがモーダルアクティブなコントローラを提示しようとした」と@cocoanut私はエラーを取得しています
バラ

1
手動セグエ「プッシュ」は非推奨です。「表示」を使用してください。この回答には詳細があります。@smileBot回答を更新してください。
NAbbas 2016年

81

このコードを使用して、カスタムセグエサブクラスをインスタンス化し、プログラムで実行しました。動作するようです。これに問題はありますか?私は困惑し、他のすべての答えを読むことができません。

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

4
MyCustomSegueには何がありますか?
Victor Engel 2013年

3
これはのカスタムサブクラスですUIStoryboardSegue
Jean-Philippe Pellet 2013年

7
@MarkAmery多くの人(私を含む)はストーリーボードの使用を避けています。それらをマージするのは難しく、渡したID performSegueWithIdentifier:がストーリーボードで本当に定義されているかどうかのコンパイル時のチェックはありません。セグエを自分で作成すれば、すべての問題を回避できます。
Jean-Philippe Pellet 2013

3
私はジーンフィリップに同意します。ストーリーボードの管理は、お尻の痛みです。もちろん、いくつかのビューを作成してここにセグエを追加し、そこにセグエを追加するのは簡単ですが、XMLで定義された16のセグエを使用して6つのビューを管理すると、3人の開発者がいじるのは大変です。とにかく、ポイントは次のとおりです。コードは制御を提供しますが、xcodeによって生成されたxmlは制御しません。
クリスティアン2013年

3
iOS7の[segue perform]でクラッシュが発生しました。他に誰かがこれを経験しているかどうかはわかりません。
Eric Chen

45

これは答えられて受け入れられると思いますが、もう少し詳細を追加したいと思います。

ログインビューを最初の画面として表示し、ログインが正しい場合はアプリケーションに代行したいという問題を解決するために私がしたこと ログインビューコントローラーからルートビューコントローラーへのセグエを作成し、「myidentifier」のような識別子を付けました。

次に、すべてのログインコードをチェックした後、ログインが正しいかどうかを呼び出します

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

私の最大の誤解は、セグエをボタンに配置し、それが見つかるとすぐにセグエを中断しようとしたことでした。


4
別のコメントとして書いたように、私はカスタムセグエをプログラムで作成して実行しています(私の回答を参照してください)。
Jean-Philippe Pellet 2013

32

UIStoryboard使用しているにコードをリンクする必要があります。でYourViewControllerUIStoryboard移動し、その周囲の境界線をクリックして、そのidentifierフィールドをNSStringコードで呼び出すに設定してください。

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

1
これが表示されますが、表示したいviewControllerがストーリーボードのNavigationControllerに埋め込まれている場合はどうなりますか?私が見つけたものから、それを埋め込むためにNavigationControllerを初期化できますが、ストーリーボードでは、表示する必要のあるビューのプッシュセグエ設定を既に持っています。
jhilgert00

1
これについて詳しく説明できますか?これは私が抱えている問題だと思いますが、これを行う方法/場所を見つけることができないようです...
jesses.co.tt '14

1
この解決策も正しい解決策です。セグエを回避することですが、問題はセグエについてです。このようにして、ストーリーボードでセグエなしで2つのシーンを接続または移行できます。
BootMaker

16

ストーリーボードにあるコントローラーの場合。

jhilgert00はあなたが探していたものですか?

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

}

または...

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

3

まあ、UIStoryBoardSegueを作成してサブクラス化することもできます。サブクラス化は、主にカスタム遷移アニメーションを提供するために使用されます。

StoryBoardを紹介するwwdc 2011のビデオを見ることができます。YouTubeでも利用できます。

http://developer.apple.com/library/ios/#documentation/UIKit/Reference/UIStoryboardSegue_Class/Reference/Reference.html#//apple_ref/occ/cl/UIStoryboardSegue


3

説明を追加したい...

よくある誤解は、事実、私がしばらくの間経験したことですが、ストーリーボードセグエはprepareForSegue:sender:メソッドによってトリガーされるというものです。そうではない。ストーリーボードセグエはprepareForSegue:sender:、その(ビューコントローラから離れた)メソッドを実装しているかどうかに関係なく実行されます。

これはPaul Hegartyの素晴らしいiTunesU講義から学びました。申し訳ありませんが、残念ながらどの講義か思い出せません。

ストーリーボードの2つのView Controller間にセグエを接続するが、実装しない場合 prepareForSegue:sender:メソッドを場合でも、セグエはターゲットのビューコントローラーにセグエします。ただし、準備されていないビューコントローラーにセグメンテーションします。

お役に立てれば。


3

ストーリーボードセグエは、ストーリーボードの外で作成することはできません。欠点はあるものの、配線する必要があります。

UIStoryboardSegueリファレンスは明確に述べています:

セグエオブジェクトを直接作成することはありません。代わりに、ストーリーボードランタイムは、2つのView Controller間でセグエを実行する必要がある場合にそれらを作成します。必要に応じて、UIViewControllerのperformSegueWithIdentifier:sender:メソッドを使用してプログラムでセグエを開始することもできます。プログラムで追加されたためにInterface Builderで使用できないソースからセグエを開始するためにそうするかもしれません。

プログラムでストーリーボードにセグエを使用して、presentModalViewController:またはpushViewController:animated:呼び出しを使用してビューコントローラーを表示するように指示できますが、ストーリーボードインスタンスが必要になります。

UIStoryboardsクラスメソッドを呼び出して、メインバンドルのバンドルnilで名前付きストーリーボードを取得できます。

storyboardWithName:bundle:


2

最初に、ストーリーボードに2つの異なるビューがあり、1つの画面から別の画面に移動する場合は、次の手順に従います。

1)。IDインスペクターでクラスファイルとストーリーボードIDを使用してすべてのビューを定義します。

2)。ナビゲーションコントローラを最初のビューに必ず追加してください。ストーリーボードでそれを選択してから、エディター>埋め込み>ナビゲーションコントローラー

3)。最初のクラスで、「secondClass.h」をインポートします

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

4)。セグエを実行する必要があるIBActionにこのコマンドを追加します

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

5)。@"second"secondviewコントローラークラス、ストーリーボードIDです。


self.storyboardする必要があります:UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];
masipcat

@masipcatとStoryボード名は、Xcodeプロジェクトの設定方法によって異なる場合があります。私の場合は「Main.storyboard」だったので、使用しましたstoryboardWithName:@"Main"
ammianus

@ sanket-chauhan最初のコントローラーがナビゲーションコントローラーに埋め込まれていない場合は、[self showDetailViewController:next sender:self];or を使用して次のビューを表示することもできます[self showViewController:next sender:self];
ammianus

1

私はリバースエンジニアリングを行い、UIStoryboardのセグエのオープンソース(再)実装を作成しました:https : //github.com/acoomans/Segway

そのライブラリを使用すると、セグエをプログラムで(ストーリーボードなしで)定義できます。

お役に立てれば幸いです。


0

実際にいくつかの問題:

まず、アップロードしたプロジェクトでは、セグエに「segue1」識別子が付いていません。

識別子なし

まだ入力していない場合は、その識別子を入力する必要があります。

次に、テーブルビューからテーブルビューにプッシュするときに、initWithNibNameを呼び出してビューコントローラを作成します。あなたは本当にInstantiateViewControllerWithIdentifierを使いたいのです。


0

のコードサンプルは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)アクションメソッドから呼び出しています。if self.commonSegue == segue {...}では、prepare(for:sender)メソッドで比較する意味は何ですか?
nayem 2017

@nayem:ではprepare(for:sender:)、宛先のView Controllerを表示する前に構成できます。もちろん、でも行うことができますactionFunction
jqgsninimo 2017

@nayem:私がこれを行う理由は、他のセグエの処理との一貫性を保つためです。
jqgsninimo 2017
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.