ストーリーボードXcode 6の適応型セグエ。プッシュは非推奨ですか?


121

Xcode 6インターフェースビルダーには、デフォルトで「サイズクラスを使用」という新しいチェックボックスがあります。ビューを適応させます。 ここに画像の説明を入力してください

ストーリーボードの2つのビューの間でセグエを作成しようとすると、新しいオプションができます。 ここに画像の説明を入力してください

代わりに古い:

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

これで、「プッシュ」と「モーダル」の代わりに「表示」と「モーダルで表示」ができました。古いオプションは非推奨としてマークされています。セグエ設定では「表示(例:プッシュ)」と呼ばれるため、「表示」オプションを選択しました

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

しかし、それはプッシュをしません。セグエアニメーションが下からスライドするように見え(モーダル)、ナビゲーションバーが消えます。

質問は:「ショー」をプッシュのように機能させるにはどうすればよいですか?可能ですか、代わりに「push(非推奨)」を使用する必要がありますか?新しいタイプのセグエに関する情報はどこにありますか?iOS8開発者ライブラリで見つけた唯一のものは、ストーリーボードユーザーインターフェイスの設計を支援することですが、「表示」セグエに関する情報はありません。

更新

私は新しいプロジェクトを作成しようとしましたが、「ショー」は実際には「プッシュ」のように機能します。私のプロジェクトの問題は、このようなコードでナビゲーションコントローラーを再利用したことが原因である可能性があると思いますが、それを修正する方法がわかりません。

if ( [segue isKindOfClass: [SWRevealViewControllerSegue class]] ) {
    SWRevealViewControllerSegue *swSegue = (SWRevealViewControllerSegue*) segue;
    
    swSegue.performBlock = ^(SWRevealViewControllerSegue* rvc_segue, UIViewController* svc, UIViewController* dvc) {
        
        UINavigationController* navController = (UINavigationController*)self.revealViewController.frontViewController;
        [navController setViewControllers: @[dvc] animated: NO ];
        [self.revealViewController setFrontViewPosition: FrontViewPositionLeft animated: YES];
    };
    
}

その後、MainViewControllerの後にNewViewControllerをプッシュしようとします。 ここに画像の説明を入力してください

更新2:

iOS 7、iOS 7.1のみの問題のようです。

回答:


97

はい、「プッシュ」の代わりに「表示」を使用します

「ショー」をプッシュのように機能させるにはどうすればよいですか?可能ですか、代わりに「push(depricated)」を使用する必要がありますか?

そうすべき; それは私のために行います。私はXcode 6ベータ2を使用しており、テストするために単一のビューテンプレートを使用しました(IB 'VC_A'で事前に作成されたビューコントローラーを呼び出しています)。次に、別のビューコントローラ( 'VC_B')を追加しました。次に、VC_Aにボタンを追加して、VC_BとVC_Bから別のVC_Aを表示します。ストーリーボードの最初のビューコントローラーとしてナビゲーションコントローラーを追加し、VC_AをrootViewControllerにすると、「push」と「show」の両方に同じ効果があります。最初のナビゲーションコントローラーがなく、「表示」を使用すると、VC_Bが下から上にスライドするという説明が表示されます。「プッシュ」しようとすると、クラッシュを起こします。プッシュを行うには、ナビゲーションコントローラが必要だからです。

新しいタイプのセグエに関する情報はどこにありますか?

そこで、ここの 'Interface Builderの新機能'セッションいくつかの情報を見つけまし。スライドを見ると、1枚のスライド(41)に変更点が記載されています。そのセッションのビデオを見ているとき、彼らがアダプティブセグエについて話し始める38:00分までスキップできます。たとえば、「表示」適応セグエは、新しいビューコントローラの表示方法を決定するときにコンテキストを考慮することを説明しています。


お返事ありがとうございます。新しいプロジェクトを作成しようとしましたが、「表示」はナビゲーションコントローラーを使用したプッシュのように機能します。私のプロジェクトでは、私は、このレッスンからサイドバーと複雑な構造を有するappcoda.com/ios-programming-sidebar-navigation-menuとプッシュ作品を、ショーはしていません。ナビコントローラーを再利用していることが理由かもしれません。再利用コードで質問を更新しました。
John Kakon、2014年

したがって、更新を確認したときに最初に目にするのは、カスタムセグエを使用しているということです。「SWRevealViewControllerSegue」なので、そうです。あなたがあなた自身のカスタムコードを実行したいのに対し、セグエ。サンプルプロジェクトをダウンロードすると、ストーリーボードファイルのセグエで「カスタム」の選択が表示されます。
スペンサーホール

私はこのセグエを意味するものではありませんでした。私は「MainViewController」の横に新しいUIViewControllerを作成することについて話していました(ナビゲーションコントローラーがあり、「更新」はそこに到達する方法を示すだけです)、新しいビューをMainViewControllerにプッシュしようとします。ストーリーボードのスクリーンショットサンプルプロジェクトで「サイズクラスの使用」を有効にして、NewViewControllerを作成し、「show」でMainViewControllerとNewViewControllerの間でセグエを作成してみてください。あなたは私が何について話しているかを見るでしょう。
John Kakon、2014年

今のところ、少なくとも私にとっては、「ショー」は「プッシュ」のように動作しましたか。
スペンサーホール

9
バグを回避するには、ビューコントローラへのすべての方法でルートにUINavigationControllerがあることを確認します。これが、アクセスされないUINavigationControllerをストーリーボードに配置することを意味する場合でも。動作を推測するために配線が使用されているようです。
スコットロバートソン

33

すでに受け入れられた答えがありますが、私はもう少し情報、おそらく以前は利用できなかった情報を提供したいと思いました。

前述のように、「プッシュ」および「モーダル」のセグエは非推奨になり、それぞれ「表示」および「現在のモーダル」に置き換えられました。Appleのドキュメントによると、新しいセグエはサイズクラスに適合するセグエにさらに分割されています。古いバージョンは、iOS 8より古いiOSバージョンをサポートするためにのみ使用してください。

次のリンクのドキュメントは、そのことと、使用可能なすべてのセグエの新旧の説明を説明しています。

ストーリーボードのシーン間にセグエを追加する

URLが将来変更される場合、これは新しいセグエごとに与えられる説明です:

公演

画面のコンテンツに応じて、詳細領域またはマスター領域にコンテンツを表示します。アプリがマスタービューと詳細ビューを表示している場合、コンテンツは詳細領域にプッシュされます。アプリがマスターまたは詳細のみを表示している場合、コンテンツは現在のビューコントローラースタックの上にプッシュされます。

詳細を表示

詳細領域にコンテンツを表示します。アプリがマスターおよび詳細ビューを表示している場合、新しいコンテンツが現在の詳細を置き換えます。アプリがマスターまたは詳細のみを表示している場合、コンテンツは現在のビューコントローラースタックの最上位を置き換えます。

モーダルに提示

コンテンツをモーダルに提示します。表示スタイル(UIModalPresentationStyle)と遷移スタイル(UIModalTransitionStyle)を選択するオプションがあります。

ポップオーバーとして提示

コンテンツを既存のビューにアンカーされたポップオーバーとして表示します。ポップオーバービューの一方の端に表示される矢印の可能な方向を指定するオプションがあります(UIPopoverArrowDirection)。アンカービューを指定するオプションもあります。


24

tldr; 正しくプッシュしていないセグエを削除し、UIView / UIControlからターゲットのビューコントローラーにドラッグして、ストーリーボードに再作成します。

他の回答には何の問題もありませんが、これは何が起こっているのか、それが起こっていることを確認する方法、および将来の問題を軽減する方法を説明しています。

バックグラウンド

私の場合、最初のビューコントローラーとしてUINavigationControllerを既に持っていても(コンテンツのUIViewControllerをルートとして)、Show Seguesはどれも機能していませんでした。

ショーセグエが壊れる理由と方法

ストーリーボードのソースxml内でセグエに関連付けられているアクションがあると、ショーセグエが機能しなくなります。これを引き起こす典型的なシナリオは、以前にコードで呼び出された手動のセグエからセグエを再定義した場合です。これにより、ストーリーボードxmlに次のビットが残ります。

<connections>
    <segue destination="85t-Z1-hxf" kind="show" identifier="ToOptions" action="showDetailViewController:sender:" id="gdZ-IX-KcN">
</connections>

Nota Bene ストーリーボードをxmlとして表示するには、ストーリーボードファイルを右クリックし、[開く]> [ソースコード]を選択します。元に戻すには、[開く]> [インターフェイスビルダー-ストーリーボード]を使用します

ストーリーボードからセグエを使用するときにカスタムアクションに対応するには、prepareForSegueをタップして宛先のビューコントローラーをインターセプトし、その場所からメソッドを呼び出すだけです。いずれにせよ、この小さなバグの副作用(バグは、セグエを再定義したときに、xmlで正しく設定されていないという事実です。つまり、セグエをUIView(またはUIControl)からターゲットビューコントローラーへ)。

残念ながら、最も直接的な解決策は失敗します。したがって、ストーリーボード内からアクションのxml属性を削除するだけでは問題は解決しません。代わりに、ストーリーボードでセグエを削除して再作成する必要があります。

ストーリーボードxmlを再作成すると、特定のセグエに関連付けられたアクションがなくなり、ショーはプッシュとして実行されます。

正しいShow SegueのサンプルXML

  <connections>
    <segue destination="RbV-Au-WV9" kind="show" identifier="ToOptions" id="5dm-os-bcS"/>
  </connections>

緩和

再発を防ぐために、可能であればprepareForSegueを使用して宛先のビューコントローラーに基づいて必要なアクションを追加することにより、手動ではないストーリーボードセグエに固執する必要があります。または、組み合わせる必要がある場合は、予防策を講じて、ショーセグエのストーリーボードxmlにアクションがアタッチされていないことを確認してください。古いプロジェクトを扱っている場合は、いくつかの問題を発見したので、ストーリーボードのソースコードに特別な注意を払う必要があります。


3
数時間後、これによりおそらく他の時間を節約できました。開くストーリーボード:ここで私は上記に基づいて提案するだろうか、あるソースコードを検索種類=「ショー」の行は以下のようなものが含まれている場合は、ルック=アクション「:送信者:showDetailViewController」、そうであれば、から削除すべてのアクション=終わりまで"。私は本当に大きなストーリーボードを持っていて、影響を受けたシークにはこのアクションパラメータが含まれていませんでしたが、別の無関係な行が含まれていました。アクションを削除すると、すべてのアダプティブシークは期待どおりに再び機能しました。トン仕事。
マーカス

これも私を救った。
Adam Bardon

1
XMLでaction属性を削除することは私の友人にとってはうまくいきました。
ブレントロイヤルゴードン


xmlファイルのaction属性を削除すると、動作します。この投稿がなければ問題を発見できなかったでしょう。
krizzzn 2017年

20

スコット・ロバートソンは、ここでコメントし、このルックスは、iOS 7のバグが好き。

iOS 8では移行が実行時に推測され(正しい動作)、iOS 7では設計時に移行が推測されます(バグのある動作)。

最も簡単な回避策は、未使用のナビゲーションコントローラーをストーリーボードに追加してリンクし、問題のビューコントローラーがこのナビゲーションコントローラーの一部になるようにすることです。実際にナビゲーションコントローラーをインスタンス化する必要はありません。ナビゲーションコントローラーに埋め込まれていることを知るには、バグのあるビューコントローラーが必要です。

注:ナビゲーションバーのシミュレーションは、これらの目的には十分ではありません。実際には、プッシュスタックにナビゲーションコントローラーが必要です。

バグを再現するには:

  1. サイズクラスを使用する新しいストーリーボードを作成します。
  2. 2つのビューコントローラを作成します(ナビゲーションコントローラはありません)。
  3. たとえば、ボタンにリンクされた表示(プッシュなど)セグエを使用して、最初のビューコントローラーに2番目のビューコントローラーを表示します。
  4. コードで、最初のビューコントローラーを表示しますが、initWithRootViewController:メソッドを介してナビゲーションコントローラーに埋め込みます。
  5. iOS 7でアプリを実行します。
  6. プッシュするボタンをタップします。
  7. iOS 7では、プッシュの代わりにモーダルトランジションが得られます。iOS8では、正しいプッシュ動作が得られます。

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

バグを修正するには:

  1. ストーリーボードにナビゲーションコントローラーを追加し、最初のビューコントローラーをルートビューコントローラーに設定します。(注:ルートビューコントローラーとして2番目を追加しても、このバグは修正されません。)
  2. ナビゲーションコントローラーにアクセスできないという警告を抑制し、回避策としてのみ存在することを文書化するために、ジャンクIDを与えます。(例workaround for show segues in iOS 7)。

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

2番目の図でナビゲーションコントローラーがどのように追加され、どの矢印も表示されないことに注意してください(つまり、ビューコントローラー識別子を使用する以外にインスタンス化する方法はありません)。


1
おかげで、ルートNavigationControllers ViewController-Stackを入れ替えるときに、NavigationControllerを使ったトリックでうまくいきました
Peter Pint

1
最良のソリューション。ありがとう
–льяГолованов15年

13

私はこれに遅れていることを知っていますが、私が学んだことを共有したいと思いました。これは実際にはバグであり、現在も存在しています(2014-12-18)。

これに関する記事をここに書きました。

簡単に再現できます。Showセグエを呼び出す前にプログラムでスタックにビューコントローラーをプッシュしない限り、iOS8ではiOS7.xでも問題なく機能します。

ストーリーボード接続を使用してスタックにプッシュするだけで機能します。しかし、どうやらコードを介してプッシュした場合、どういうわけか、プッシュされたnavigationControllerプロパティは次のようUIViewControllerになりnilます。呼び出しShowを行うと、スタックを制御するナビゲーションがないため、モーダルと見なされます。

これまでの回避策は、コード経由でプッシュしないか(実現不可能)、現在は非推奨のを使用することですPush

レーダーを提出しました(記事のリンク)。Appleがこの問題を修正することを期待して、自由に複製を提出してください。


3
これはまさに私の問題でした、ありがとう!廃止されたプッシュを使用することは、この場合はそれほど問題のない解決策のようです。
Moshe Gottlieb 2014

別の回避策は、(未使用の)ナビゲーションコントローラーをストーリーボードに追加することです。stackoverflow.com/questions/24184003/…を
Senseful

違う!ここで発生し、その原因はプログラムによるプッシュではありません。私の場合、Showセグエを実行し、2番目のShowセグエでモーダルに表示されます、ソリューション?
Frade

@Fradeは、再現可能なgithubリポジトリにリンクできますか?iOSのどのバージョンで実行していますか?
esttorhe 2015年

民間プロジェクトが...それが起こる(第2)を実行しようとすると、ShowiOSの7上のViewControllerの
フラージ

2

Xcode 7とiOS 7.1.2のセグエにも同じ問題がありました。Show segues(iOS 8の新機能)は、iOS 7のモーダルセグエのように機能し、ストーリーボードでXcodeを使用してセグエタイプを定義するときに、View ControllerをNavigation Controllerスタックにプッシュできません。そのため、ビューコントローラーがスタックにプッシュされず、ポップできないため、self.navigationControllerはnilを返します。

iOS 7でアプリを動作させる必要があるのに、Appleがこのケースの通知をXcodeに追加しなかった理由がわかりません。Pushメソッドは非推奨であると言われていますが、iOS 7 ではShowが正しく動作しません。

問題を解決するために私は何をしましたか:

.hでMYShowSegueクラスを作成しました

#import <UIKit/UIKit.h>

@interface MYShowSegue : UIStoryboardSegue

@end

そして、1つの実行メソッドのみを含む.mファイル:

#import "MYShowSegue.h"

@implementation MYShowSegue

- (void) perform {

    if ([[[self sourceViewController] navigationController] respondsToSelector:@selector(showViewController:sender:)]) {

        id sender = nil;
        [[[self sourceViewController] navigationController] showViewController:[self destinationViewController] sender:sender];
    }else{

        [[[self sourceViewController] navigationController] pushViewController:[self destinationViewController] animated:YES];
    }
}

@end

ストーリーボードの各セグエにカスタムタイプを設定し、そのための新しいクラスを選択する必要があります(私の場合はMYShowSegue)。

カスタムセグエの例

このソリューションは、iOS 7アプリの完全なサポートを得るのに役立ちます。アプリはpushViewControllerメソッドを使用してビューをプッシュします。iOS8,9などの場合、セグエは新しい(iOS 8)メソッドshowViewControllerで動作します

ストーリーボードのすべてのセグエで同じことを行うことを忘れないでください。


素敵な解決策-私に働きました(「未使用」のナビゲーションコントローラーを追加する代わりに...
LaurenzGlück16年

1

これはまだiOS 10.xで起こっています

セグエを削除して復元しても、何も解決されませんでした。

問題:必要な機能は「プッシュ」(実際には詳細の表示)としてのみ動作する7つのセグエでしたが、実際、私が追加した最初のセグエだけがプッシュし、その他はすべてモーダルに動作します。これは、Interface Builderが各セグエを同一に説明しているにもかかわらずです。

解決策:アクションのない6つのセグエにアクションを追加する必要がありました。

オリジナルのストーリーボードXML

<connections>
  <segue destination="tIr-4a-WfZ" kind="showDetail" identifier="A" action="showViewController:sender:" id="8yd-Ne-7KA"/>
  <segue destination="4mB-YE-5dM" kind="showDetail" identifier="B" id="Uod-JC-786"/>
  <segue destination="Qh5-bJ-KcE" kind="showDetail" identifier="C" id="3PW-nV-hWl"/>
  <segue destination="EI6-f4-QBB" kind="showDetail" identifier="D" id="WUK-ju-KDm"/>
  <segue destination="nTz-N4-fpW" kind="showDetail" identifier="E" id="Id6-bW-Huc"/>
  <segue destination="JEp-CH-6dW" kind="showDetail" identifier="F" id="G0L-XW-7f4"/>
  <segue destination="AET-S1-O6h" kind="showDetail" identifier="G" id="3NK-93-wTy"/>
</connections>

showViewController:senderを追加してこれを変更しました

<connections>
  <segue destination="tIr-4a-WfZ" kind="showDetail" identifier="A" action="showViewController:sender:" id="8yd-Ne-7KA"/>
  <segue destination="4mB-YE-5dM" kind="showDetail" identifier="B" action="showViewController:sender:" id="Uod-JC-786"/>
  <segue destination="Qh5-bJ-KcE" kind="showDetail" identifier="C" action="showViewController:sender:" id="3PW-nV-hWl"/>
  <segue destination="EI6-f4-QBB" kind="showDetail" identifier="D" action="showViewController:sender:" id="WUK-ju-KDm"/>
  <segue destination="nTz-N4-fpW" kind="showDetail" identifier="E" action="showViewController:sender:" id="Id6-bW-Huc"/>
  <segue destination="JEp-CH-6dW" kind="showDetail" identifier="F" action="showViewController:sender:" id="G0L-XW-7f4"/>
  <segue destination="AET-S1-O6h" kind="showDetail" identifier="G" action="showViewController:sender:" id="3NK-93-wTy"/>
</connections>
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.