如何弹回到根视图控制器,然后推送到另一个视图?

Rya*_*yan 15 xcode cocoa uiviewcontroller uinavigationcontroller ios

我正在编写一个具有3个视图控制器的简单应用程序.根视图控制器是一个item listing基本的表视图.关闭此视图控制器,我根据一些用户交互推送两个不同的视图控制器 - 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];

                                          }];

}
Run Code Online (Sandbox Code Playgroud)

Dav*_*ong 39

如果我理解正确,你有一堆视图控制器:

A (root) - B - C - D - E
Run Code Online (Sandbox Code Playgroud)

而你希望它成为:

A (root) - F
Run Code Online (Sandbox Code Playgroud)

对?在这种情况下:

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];
Run Code Online (Sandbox Code Playgroud)

斯威夫特4

// get current view controllers in stack and replace them
let viewControllers = self.navigationController!.viewControllers
let newViewControllers = NSMutableArray()

// preserve the root view controller
newViewControllers.add(viewControllers[0])
// add the new view controller
newViewControllers.add(viewThreadController)
// animatedly change the navigation stack
self.navigationController?.setViewControllers(newViewControllers as! [UIViewController], animated: true)
Run Code Online (Sandbox Code Playgroud)

  • ^ @LysannSchlegel这就是重点.它从E-> F动画,但是如果你点击后退按钮,你将转到A而不是E.基本上,将后面的堆栈清理到父视图,中间没有任何时髦/意外的动画! (2认同)

M.C*_*.C. 8

我认为
[self.navigationController pushViewController:viewThreadController animated:YES]; 使用与之前的语句不同的NavigationController.因为在弹出到根视图控制器后,您将松开您所在的导航控制器.请使用此代码解决此问题

UINavigationController *nav = self.navigationController; 
[self.navigationController popToRootViewControllerAnimated:NO];
[nav pushViewController:viewThreadController animated:YES];
Run Code Online (Sandbox Code Playgroud)

我也认为这不会解决你的整个问题.你可能会收到一个错误,说两个快速弹出和推送可能导致NavigationController无效.
要解决这个问题,您可以在第二个视图控制器的viewDidDissappear方法中推送NavigationController,或者将其推送到主视图控制器(项目列表)中的viewDidAppear方法中.


Coc*_*aEv 6

完成您想要做的事情的一种简单方法是在主根视图控制器中构建一些简单的逻辑 - (void)viewWillAppear方法并使用委托回调来翻转逻辑开关.基本上是根控制器的"后向引用".这是一个简单的例子.

主根控制器(考虑这个控制器a) - 好吧叫它controllerA设置一个属性来跟踪跳转状态

@property (nonatomic) BOOL jumpNeeded;
Run Code Online (Sandbox Code Playgroud)

设置一些逻辑

- (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];
    }   
}
Run Code Online (Sandbox Code Playgroud)

现在,在你的主根控制器中,当选择一个tableview行时,在你的tableView中推送到controllerB时做了类似的事情.

[self performSegueWithIdentifer@"controllerB" sender:self];
Run Code Online (Sandbox Code Playgroud)

然后实施你准备segue方法

- (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
}
Run Code Online (Sandbox Code Playgroud)

现在转到controllerB你需要设置一个名为"delegate"的属性来保存后引用,你需要从根控制器导入头文件

#import "controllerA"

@property (nonatomic,weak) controllerA *delegate;
Run Code Online (Sandbox Code Playgroud)

然后在弹回控制器A之前,设置标志

   self.delegate.jumpNeeded = YES;
    [self.navigationController popViewControllerAnimated:YES];
Run Code Online (Sandbox Code Playgroud)

这就是它.您无需对controllerC执行任何操作.还有其他一些方法可以做,但这对您的需求非常直接.希望它对你有帮助.


小智 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
Run Code Online (Sandbox Code Playgroud)