2015-09-15 3 views
6

はどうすればデフォルトのナビゲーションは、[戻る]ボタンがに私を取るビューコントローラを変更できますか?戻るボタンは通常、前のView Controllerに戻ります。しかし、2つのView Controllerで元に戻したいのですが?私はバック・ボタンが私を連れてくるビュー・コントローラーを変更したいのです。私はカスタムの戻るボタンを作成することを好むわけではありません。他の方法はありますか?おそらく巻き戻しのセグが後ろのボタンなどにリンクされていますか?変更先は

+0

「しかし、2つのView Controllerで元に戻したいのですが」とはどういう意味ですか? –

+1

@CalebKleveter私は、別のビューコントローラに移動したいのですが、前のコントローラではない場合はどうすればいいですか? –

答えて

6

おそらく最も簡単な方法は、navigationController.setViewControllers(controllers, animated: true)を使用することです。

あなたが提示したときにこのカスタムセグエを使用し、バック一つだけの代わりに、コントローラAから2つのコントローラを移動したい場合:ここで

class ReplaceControllerSegue: UIStoryboardSegue { 
    override func perform() { 
     if let navigationController = sourceViewController.navigationController as UINavigationController? { 
      var controllers = navigationController.viewControllers 
      controllers.removeLast() 
      controllers.append(destinationViewController) 
      navigationController.setViewControllers(controllers, animated: true) 
     } 
    } 
} 

は、Interface Builderであなたのセグエのためのカスタムクラスを設定する方法素敵なチュートリアルです:http://blog.jimjh.com/a-short-tutorial-on-custom-storyboard-segues.html

あなたがこのカテゴリを使用して、コードを介してコントローラを提示している場合:

extension UINavigationController { 
    func replaceCurrentViewControllerWith(viewController: UIViewController, animated: Bool) { 
     var controllers = viewControllers 
     controllers.removeLast() 
     controllers.append(viewController) 
     setViewControllers(controllers, animated: animated) 
    } 
} 

は、それからちょうどを使用self.navigationControllerPushViewController(newController, animated: true)の代わりに

それはあなたが必要なだけのコントローラを削除するには、このコードを調整するのは簡単です。

+0

別のUIStoryboardSegue Cocoa Touchクラスを作成する必要がありますか?もしそうなら、私はこのクラスをどのように使うべきですか?私はクラスをいくつかのセグに割り当てる必要がありますか? –

+1

上記のカスタムUIStoryboardSegueクラスのコードを投稿しました。ここでは、インターフェイスビルダーでsegueのカスタムクラスを割り当てる方法をチュートリアルです:http://blog.jimjh.com/a-short-tutorial-on-custom-storyboard-segues.html – glyuck

+0

OH GOD!どうもありがとうございます!私はそれのためにそれを捜したが、私はそれを得なかった!どうもありがとう! –

0

あなたは、このようなカスタムバックボタンを追加することによってこれを行うことができます。ナビゲーションバーの[戻る]ボタンをタップしてカスタムアクションハンドラを追加します。

+ (void)addCustomBackButtonForController:(id <MyCustomBackButtonDelegate>)iViewController withNavBar:(UINavigationController *)iNavController andNavItem:(UINavigationItem *)iNavItem { 
    if ([self isIOS7orAbove]) { 
     UIImage *backArrow = [UIImage imageNamed:kMyIOS7BackButtonImage]; 
     UIButton *aBackButton = [UIButton buttonWithType:UIButtonTypeSystem]; 
     CGSize aBackButtonTextSize = [MyLocalizedBackButton sizeWithFont:[UIFont systemFontOfSize:17.0]]; 
     aBackButton.frame = CGRectMake(0.0, 0.0, aBackButtonTextSize.width + backArrow.size.width, iNavController.navigationBar.frame.size.height); 
     aBackButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft; 
     SEL backSelector = NSSelectorFromString(@"backAction"); 
     [aBackButton addTarget:iViewController action:backSelector forControlEvents:UIControlEventTouchUpInside]; 
     [aBackButton setTitle:MyLocalizedBackButton forState:UIControlStateNormal]; 
     [aBackButton setImage:backArrow forState:UIControlStateNormal]; 
     [aBackButton setExclusiveTouch:YES]; 

     if ([self isIOS7orAbove]) { 
      aBackButton.titleLabel.font = [UIFont systemFontOfSize:17.0]; 
     } else { 
      aBackButton.titleLabel.font = [UIFont boldSystemFontOfSize:12.0]; 
     } 

     UIBarButtonItem *aLeftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:aBackButton]; 
     UIBarButtonItem *aNegativeSpacer = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil]; 
     aNegativeSpacer.width = kMyIOS7BarButtonNegativeSpacerWidth; 
     iNavItem.leftBarButtonItems = @[aNegativeSpacer, aLeftBarButtonItem]; 
    } else { 
     UIButton *aCustomBackButton = [UIButton buttonWithType:101]; 
     SEL backSelector = NSSelectorFromString(@"backAction"); 
     [aCustomBackButton addTarget:iViewController action:backSelector forControlEvents:UIControlEventTouchUpInside]; 
     [aCustomBackButton setTitle:MyLocalizedBackButton forState:UIControlStateNormal]; 
     [aCustomBackButton setExclusiveTouch:YES]; 

     if ([self isIOS7orAbove]) { 
      aCustomBackButton.titleLabel.font = [UIFont systemFontOfSize:kFontSize17]; 
     } else { 
      aCustomBackButton.titleLabel.font = [UIFont boldSystemFontOfSize:kFontSize12]; 
     } 

     UIBarButtonItem *aLeftBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:aCustomBackButton]; 
     iNavItem.leftBarButtonItem = aLeftBarButtonItem; 
    } 
} 
+0

カスタムバックボタンなしでこれを実装したい場合は、スワイプできなくなりバックアニメーションが失われます。多くのアプリでカスタムバックボタンなしでこれを実装することができました。私はこれもできる方法はありますか? –

+0

スワイプできなくなりバックアニメーションが失われるということはどういう意味ですか? – Abhinav

+0

あなたは、ユーザーがエッジからスワイプしてゆっくりと前のビューコントローラに移行できることを知っていますか? –

6

willMoveToParentViewControllerを上書きできます。このメソッドは、ビューコントローラがコンテナビューコントローラに追加または削除される前に呼び出されます(UINavigationControllerなど)。追加時には、parentパラメータにはコンテナビューコントローラが含まれています。これを削除すると、parentパラメータはnilになります。そうのようなあなたは、(アニメーションなしに)除去することができる。この時点で

ナビゲーションスタック内の最後のビューコントローラへの第2:

のObjective-C

- (void)willMoveToParentViewController:(UIViewController *)parent 
{ 
    [super willMoveToParentViewController:parent]; 

    if (parent == nil) { 
     NSArray *viewControllers = self.navigationController.viewControllers; 
     NSUInteger viewControllersCount = viewControllers.count; 
     if (viewControllersCount > 2) { 
      NSMutableArray *mutableViewControllers = [NSMutableArray arrayWithArray:viewControllers]; 
      [mutableViewControllers removeObjectAtIndex:(viewControllersCount - 2)]; 
      [self.navigationController setViewControllers:[NSArray arrayWithArray:mutableViewControllers] animated:NO]; 
     } 
    } 
} 

スウィフト

override func willMoveToParentViewController(parent:UIViewController?) 
{ 
    super.willMoveToParentViewController(parent) 

    if (parent == nil) { 
     if let navigationController = self.navigationController { 
      var viewControllers = navigationController.viewControllers 
      var viewControllersCount = viewControllers.count 
      if (viewControllersCount > 2) { 
       viewControllers.removeAtIndex(viewControllersCount - 2) 
       navigationController.setViewControllers(viewControllers, animated:false) 
      } 
     } 
    } 
} 

複数のメッセージを削除することも、新しいメッセージを追加することもできます。完了したら、配列に少なくとも2つのView Controllerが含まれていることを確認してください(最後のものは削除されています。

はまた、この方法がnilパラメータで複数回呼び出すことができるよりも、注意してください。たとえば、エッジ・スワイプを使用してビュー・コントローラーをポップして途中で中止しようとすると、試行するたびにメソッドが呼び出されます。追加のチェックを追加して、必要以上に多くのビューコントローラを削除しないようにしてください。

+1

この回答を見つけるのはとても難しかったです。しかし、あなたはそれをやった!ありがとう! –

+0

最初はうまくいくとは思えません。 ['viewWillDisappear'](http://stackoverflow.com/a/3445994/426227)よりも優れています。 – testing

0

これは上記のことを繰り返すことができますが、私は最後のVewControllerのviewDidLoadを変更することでこれを解決しました。 "theControllers"はUIViewController型の配列です。私の場合、私はちょうどルートビューコントローラに戻りたいので、配列にはルートビューコントローラ(最初)と現在のビューコントローラ(最後)が含まれています。次に、 "setViewControllers"は、現在のスタックを私が作成したものに置き換えます。

override func viewDidLoad() { 
    super.viewDidLoad() 
    var theControllers = [UIViewController]() 
    theControllers.append(self.navigationController!.viewControllers.first!) 
    theControllers.append(self.navigationController!.viewControllers.last!) 
    self.navigationController?.setViewControllers(theControllers, animated: false) 
} 
関連する問題