2012-08-05 11 views
13

私は3つのView Controllerを持つシンプルなアプリケーションを書いています。ルートビューコントローラはitem listingで、基本的なテーブルビューです。このビューコントローラをオフにして、いくつかのユーザーインタラクションに基づいて2つの異なるビューコントローラ、つまりcreate itemビューコントローラまたはview itemビューコントローラを押します。ルートビューコントローラに戻ってポップアップするが、別のビューにプッシュする方法は?

ストーリーボードは、Vなどのように見えます。

私のcreate itemビューコントローラでは、ユーザーが新しいアイテムを作成するときにルートビューコントローラにポップアップしたいが、次にコントローラをview itemにプッシュして新しく作成したアイテムを見ることができるようにしたい。

私はこれを動作させることができないようです。ルートビューコントローラにポップバックするのは簡単ですが、コントローラview itemを押すことができません。

アイデア?私は以下のコードを貼り付けました。 pop関数は機能しますが、新しいビューは表示されません。

- (void) onSave:(id)sender { 

    CLLocation *currentLocation = [[LocationHelper sharedInstance] currentLocation]; 

    // format the thread object dictionary 
    NSArray* location = @[ @(currentLocation.coordinate.latitude), @(currentLocation.coordinate.longitude) ]; 
    NSDictionary* thread = @{ @"title": _titleField.text, @"text": _textField.text, @"author": @"mustached-bear", @"location": location }; 

    // send the new thread to the api server 
    [[DerpHipsterAPIClient sharedClient] postPath:@"/api/thread" 
             parameters:thread 
              success:^(AFHTTPRequestOperation *operation, id responseObject) { 

               // init thread object 
               Thread *thread = [[Thread alloc] initWithDictionary:responseObject]; 

               // init view thread controller 
               ThreadViewController *viewThreadController = [[ThreadViewController alloc] init]; 
               viewThreadController.thread = thread; 

               [self.navigationController popToRootViewControllerAnimated:NO]; 
               [self.navigationController pushViewController:viewThreadController animated:YES]; 

              } 
              failure:^(AFHTTPRequestOperation *operation, NSError *error) { 

               [self.navigationController popToRootViewControllerAnimated:YES]; 

              }]; 

} 
+0

"アイテムの作成"と "アイテムの表示"で異なるビューコントローラを作成しません。アイテムを作成した後にアイテムを表示することができますが、アイテムを表示した後にアイテムを編集する可能性が常にある可能性が常にあります。 1つのビュー・コントローラを作成し、表示し、編集できるように、1つのビュー・コントローラを設計する方が簡単です。ほとんどのアプリはこのように設計しています。あなたの周りのセグエイティング時間を節約してください。 – Rick

答えて

6

あなたがやりたいことを達成するための簡単な方法は、あなたのメインのルートビューコントローラにいくつかの簡単なロジックを構築することです。基本的にルートコントローラへの「バックリファレンス」です。ここに簡単な例があります。

メインルートコントローラ(このコントローラaを考える) - まあ、それは がで

@property (nonatomic) BOOL jumpNeeded; 

セットアップ

- (void)viewWillAppear:(BOOL)animated { 
    [super viewWillAppear:animated]; 
    self.jumpNeeded ? NSLog(@"jump needed") : NSLog(@"no jump needed"); 

    if (self.jumpNeeded) { 
     NSLog(@"jumping"); 
     self.jumpNeeded = NO; 
     [self performSegueWithIdentifier:@"controllerC" sender:self]; 
    } 
} 

でいくつかのロジック、ジャンプの状態を追跡するためにプロパティを設定しcontrollerA呼び出しますあなたのメインルートコントローラは、テーブルビューの行が選択されたときにこのような何かをする あなたのテーブルビューでコントローラBにプッシュすると、メソッドが選択されました

[self [email protected]"controllerB" sender:self]; 

、あなたのセグエ方法

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 

    //setup controller B 
    if([segue.identifier isEqualTo:@"controllerB"]){ 
    ControllerB *b = segue.destinationViewController; 
    b.delegate = self; //note this is the back reference 
    } 

    //implement controller c here if needed 
} 

の準備を実装する今、あなたは後方参照 を保持するために、「デリゲート」と呼ばれるプロパティを設定する必要があり、あなたからヘッダファイルをインポートする必要がcontrollerB に移動あなたはcontrollerAに戻ってポップ直前に、ルートコントローラ

#import "controllerA" 

@property (nonatomic,weak) controllerA *delegate; 

、あなたはフラグ

に設定します

とそれについてです。あなたはcontrollerCで何もする必要はありません。他にもいくつかの方法がありますが、これはあなたのニーズにかなり簡単です。それがあなたのために働くことを望みます。

+0

私はこれを答えに選びました。代議員は私が終わったルートだったからです。私はpush segueを一斉に中止し、 'item create 'ビューのためにモーダルセグを使いました。 – Ryan

+0

ヒントは、あなたのために働いた方向に行くことができてうれしいです。運が良かった! – CocoaEv

0

ポップバックはすべての割り当てを解除するので、これは可能ではないと思います。

もっと良い方法は、モデルのシングルトンクラスにデータを入れて、rootviewcontrollerにポップし、ポップが終わるのを待ち受けることです。次に、モデルにいくつかのデータが保存されているかどうかをチェックして、新しいViewControllerをプッシュする必要があるかどうかを確認します。

6

だと思います。
[self.navigationController pushViewController:viewThreadController animated:YES]; は、それ以前の文とは別のNavigationControllerを使用しています。 ルートビューコントローラにポップした後、あなたがしているナビゲーションコントローラを失うので。代わりに

UINavigationController *nav = self.navigationController; 
[self.navigationController popToRootViewControllerAnimated:NO]; 
[nav pushViewController:viewThreadController animated:YES]; 

をこのコードを使用すると、私もこれは文句を言わないあなたの全体の問題を解決することを考えていることを解決します。おそらく、2つの高速なポップとプッシュがNavigationControllerを無効にする可能性があるというエラーが表示されます。
これを解決するには、2番目のView ControllerのviewDidDissAppearメソッドでNavigationControllerを押すか、Main View Controller(アイテムリスト)のviewDidAppearメソッドで押します。

+0

私の習得:アニメーションを使用する場合:はい、それは意図したように動作しませんが、アニメーション化されます:いいえ、ジョブを行います。そして、popToRootが短いので、私はそれを使用しました。それが役に立てば幸い! – kjoelbro

+0

popToRootControllerを使うだけで、ここの答えが分かります。viewControllerスタックで何か面白いことをする必要はありません。また、プッシュはいつものように正常に動作します。 –

36

私が正しくあなたを理解する場合は、ビューコントローラのスタックを持っている:

A (root) - B - C - D - E 

をそして、あなたはそれがなりたい:

A (root) - F 

右?その場合には: - (無効)viewWillAppearメソッドとロジックスイッチを入れるために、デリゲートのコールバックを使用

NSArray *viewControllers = self.navigationController.viewControllers; 
NSMutableArray *newViewControllers = [NSMutableArray array]; 

// preserve the root view controller 
[newViewControllers addObject:[viewControllers objectAtIndex:0]]; 
// add the new view controller 
[newViewControllers addObject:viewThreadController]; 
// animatedly change the navigation stack 
[self.navigationController setViewControllers:newViewControllers animated:YES]; 
+0

これは、ビューEからビューFにアニメートされます。 –

+2

^@LysannSchlegelそれがポイントです。それはE-> Fでアニメーションしますが、戻るボタンを押すと、EではなくAに移動します。基本的に、間にファンキー/予期しないアニメーションを使わずに、親ビューに戻ることができます。 – DiscDev

+1

Daveの答えは素晴らしいです.UINavigationControllerのカテゴリで次のレベルの再利用に移行してください:http://stackoverflow.com/a/25771209/1103584 – DiscDev

5

私たちのアプリケーションで使用するDave DeLongの答えに基づいて、UINavigationControllerのカテゴリを共有することで、必要に応じて戻るボタンを常に動作させることができます。

@implementation UINavigationController (PushNewAndClearNavigationStackToParent) 

- (void) pushNewControllerAndClearStackToParent:(UIViewController*)newCont animated:(BOOL)animated 
{ 
    NSArray *viewControllers = self.viewControllers; 
    NSMutableArray *newViewControllers = [NSMutableArray array]; 
     
    // preserve the root view controller 
    [newViewControllers addObject:[viewControllers firstObject]]; 
    // add the new view controller 
    [newViewControllers addObject:newCont]; 
    // animatedly change the navigation stack 
    [self setViewControllers:newViewControllers animated:animated]; 
} 

@end 
1
NSArray *viewControllers = self.navigationController.viewControllers; 
NSMutableArray *newViewControllers = [NSMutableArray array]; 

// preserve the root view controller 
for(int i = 0; i < [viewControllers count];i++){ 
    if(i != [viewControllers count]-1) 
     [newViewControllers addObject:[viewControllers objectAtIndex:i]]; 
} 
// add the new view controller 
[newViewControllers addObject:conversationViewController]; 
// animatedly change the navigation stack 
[self.navigationController setViewControllers:newViewControllers animated:YES]; 
+0

あなたの答えを詳しく説明してください。あなたが提供するソリューションについてもう少し詳しく説明してください。 – abarisone

0

私はインスピレーションとしてDaveの答えを使用し、スウィフトのためにこれを作った:

let newViewControllers = NSMutableArray() 
newViewControllers.addObject(HomeViewController()) 
newViewControllers.addObject(GroupViewController()) 
let swiftArray = NSArray(array:newViewControllers) as! Array<UIViewController> 
self.navigationController?.setViewControllers(swiftArray, animated: true) 
  1. は(HomeViewControllerを交換してください)あなたは下のView Controllerが
  2. GroupViewControllerを交換したいものは何でもして()をあなたのトップビューコントローラにしたいもので置き換えます
0

あなたがしたいことが同じナビゲーションコントローラーの中でどのようにナビゲートしていても...あなたはnavigationStack A.K.Aにアクセスできます。 viewControllerを開き、必要な順序でviewcontrollersを設定するか、いくつかを追加または削除します。 これは、これを行うための最もクリーンでネイティブな方法です。

 UINavigationController* theNav = viewControllerToDismiss.navigationController; 
     UIViewController* theNewController = [UIViewController new]; 
     UIViewController* rootView = theNav.viewControllers[0]; 
     [theNav setViewControllers:@[ 
            rootView, 
            theNewController 
            ] animated:YES]; 

例外が発生しないように必要な検証を行います。

関連する問題