2015-09-15 11 views
6

Wie kann ich den Ansichts-Controller ändern, zu dem die Standardnavigation zurück-Taste führt? Die Zurück-Schaltfläche führt Sie normalerweise zum vorherigen Ansichtscontroller zurück. Aber was, wenn ich möchte, dass es von zwei View-Controllern zurückgeht? Ich meine, ich möchte den View-Controller wechseln, den mich der Zurück-Button annimmt. Ich bevorzuge es, eine benutzerdefinierte Zurück-Schaltfläche zu erstellen. Gibt es einen anderen Weg? Wahrscheinlich ein Abwicklungs-Segment, das mit dem Zurück-Knopf oder etwas verbunden ist?Ziel der Navigation ändern Schaltfläche Zurück

+0

Was meinst du mit ‚Aber was ist, wenn ich will es von zwei View-Controller zurück gehen‘? –

+1

@CalebKleveter Ich meine was, wenn ich zu einem anderen View-Controller und nicht dem vorherigen gehen möchte? –

Antwort

6

Der einfachste Weg, um ein gewünschtes Verhalten zu erreichen, ist navigationController.setViewControllers(controllers, animated: true).

Wenn Sie 2 Controller wieder von der Steuerung A gehen wollen statt nur einem, benutzen Sie diese benutzerdefinierten segue wenn A präsentiert:

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) 
     } 
    } 
} 

Hier ist nettes Tutorial, wie benutzerdefinierte Klasse für Ihre segue in Interface Builder setzen : http://blog.jimjh.com/a-short-tutorial-on-custom-storyboard-segues.html

Wenn Sie Controller über Code präsentiert werden, verwenden Sie diese Kategorie:

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

nur dannverwendenanstelle von self.navigationControllerPushViewController(newController, animated: true).

Es ist einfach, diesen Code anzupassen, um so viele Controller wie nötig zu entfernen.

+0

Sollte ich eine separate UIStoryboardSegue Cocoa Touch Klasse dafür erstellen? Und wenn ja, wie soll ich diesen Kurs nutzen? Wie sollte ich die Klasse einigen Segmenten zuweisen oder was? –

+1

Ich habe Code für benutzerdefinierte UIStoryboardSegue-Klasse oben veröffentlicht. Hier ist ein Tutorial, wie benutzerdefinierte Klasse für segue in Interface Builder zuweisen: http://blog.jimjh.com/a-short-tutorial-on-custom-storyboard-segues.html – glyuck

+0

OH GOTT! Ich danke dir sehr! Ich habe SO dafür gesucht, aber ich habe es nicht verstanden! Danke vielmals! –

0

Sie können dies tun, indem Sie eine benutzerdefinierte Schaltfläche wie folgt hinzufügen. Fügen Sie Ihren benutzerdefinierten Aktionshandler hinzu, indem Sie in der Navigationsleiste auf die Schaltfläche Zurück tippen.

+ (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

Ich möchte dies ohne eine benutzerdefinierte Schaltfläche zurück implementieren, sonst kann ich nicht zurück wischen und die Back-Animation wird verloren gehen. Viele Apps konnten dies ohne eine benutzerdefinierte Zurück-Schaltfläche implementieren. Kann ich das auch irgendwie machen? –

+0

Was meinst du mit wird nicht zurück wischen können und die Rückenanimation wird verloren gehen? – Abhinav

+0

Sie wissen, dass der Benutzer vom Rand wischen und langsam zum vorherigen Ansichtscontroller wechseln kann? –

6

Sie können willMoveToParentViewController überschreiben. Diese Methode wird aufgerufen, bevor der Ansichtscontroller einem Containeransicht-Controller hinzugefügt oder daraus entfernt wird (z. B. UINavigationController). Wenn der Parameter parent hinzugefügt wird, enthält er den Containeransicht-Controller. Wenn er entfernt wird, ist der Parameter parent Null.

An dieser Stelle Sie (ohne Animation), vorletztes View-Controller in der Navigationsstapel wie so entfernen:

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

Swift

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) 
      } 
     } 
    } 
} 

Sie können auch mehrere entfernen oder neue hinzufügen. Stellen Sie nur sicher, dass Ihr Array, wenn Sie fertig sind, mindestens zwei View-Controller enthält, wobei der letzte unverändert ist (der letzte wird entfernt und nach dem Aufruf dieser Methode automatisch aus dem Array entfernt).

Beachten Sie auch, dass diese Methode mehr als einmal mit einem Null-Parameter aufgerufen werden kann. Wenn Sie z. B. versuchen, den Ansichtscontroller mit dem Kantenwischen zu öffnen, aber in der Mitte abbrechen, wird die Methode bei jedem Versuch aufgerufen. Stellen Sie sicher, dass Sie zusätzliche Prüfungen hinzufügen, um sicherzustellen, dass Sie nicht mehr View-Controller entfernen, als Sie möchten.

+1

Es war so schwierig, diese Antwort zu finden. Aber du hast es geschafft! Vielen Dank! –

+0

Scheint in erster Linie zu funktionieren (ich kenne noch nicht alle meine Randfälle). Funktioniert besser als ['viewWillDisappear'] (http://stackoverflow.com/a/3445994/426227). – testing

0

Dies kann nur wiederholen, was oben gesagt wurde, aber ich löste dies durch Ändern von ViewDidLoad in der letzten VewController. "theControllers" ist ein Array vom Typ UIViewController. In meinem Fall wollte ich nur zum Root-View-Controller zurückkehren, so dass das Array nur den Root-View-Controller (zuerst) und den aktuellen View-Controller (zuletzt) ​​enthält.Dann ersetzt "setViewControllers" den aktuellen Stapel durch den von mir erstellten Stapel.

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) 
} 
Verwandte Themen