本文介绍了UINavigationController popToRootViewController,然后立即推送新视图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个带有两个选项卡的 tabBarController,其中第一个包含一个 NavigatorController 的实例.navigatorController 使用自定义视图控制器peersViewController"启动,该视图控制器列出了 tableView 上的所有网络对等点.选择一个对等点后,FilesListViewController"的一个实例(列出 c: 目录中的文件)被推送到 navigationController 堆栈中.

在这个 filesListViewController 中,我有一个按钮可以让它导航到文档目录.为此,我将接口连线以在 rootViewController 中调用 gotoDirectory:(NSString*)path 方法:

- (void)gotoDirectory:(NSString*)path {[[self navigationController] popToRootViewControllerAnimated:YES];NSArray *files = [self getFilesFromPeerAtPath:path];FilesListViewController *filesVC = [[FilesListViewController alloc] initWithFiles:files];[[self navigationController] pushViewController:filesVC 动画:YES];[filesVC 发布];}

但是,当我按下该按钮时,navigationController 确实将我的视图弹出到根视图控制器,但随后我实例化的 FilesListViewController 没有出现.从日志中,我知道确实调用了自定义 initWithFiles 方法,并且确实发生了网络东西来获取文件名.

这件事有些奇怪.我尝试单击第二个选项卡,然后单击返回第一个选项卡,然后哇啦!我需要的文件名在那里.看起来数据和文件ListViewController确实被推入了navigatorController堆栈,但是显示没有刷新而是卡在rootViewController(peersViewController)的屏幕上.

我做错了什么吗?

--本.

-- 发布问题 15 分钟后编辑.我找到了一种解决方法,但让我感到困扰的是 pop 然后 push 不起作用.

- (void)gotoDirectory:(NSString*)path {PeersListViewController *rootViewController = (PeersListViewController*)[[[self navigationController] viewControllers] objectAtIndex:0];[[self navigationController] setViewControllers:[NSArray arrayWithObject:rootViewController]];FilesListViewController *filesVC = [[FilesListViewController alloc] initWithFiles:files];[[self navigationController] pushViewController:filesVC 动画:YES];[filesVC 发布];}

navigationController 似乎不应该以这种方式被规避,而且我可能不得不释放原始堆栈中的所有 viewController.然而,这确实适用于 iphone 3.0 模拟器.

如果我使用这段代码,应该如何处理内存释放?我应该获取视图控制器的原始 NSArray 并释放所有内容吗?

解决方案

这个问题的问题和解决方法其实非常简单.

调用 [self.navigationController popToRootViewControllerAnimated:YES]self.navigationController 设置为 nil.当您随后调用 [self.navigationController pushViewController:someOtherViewController] 时,您实际上是在向 nil 发送一条消息,它什么都不做.

要解决此问题,只需设置对 navigationController 的本地引用并使用它:

UINavigationController * navigationController = self.navigationController;[navigationController popToRootViewControllerAnimated:NO];[navigationController pushViewController:someOtherViewController 动画:YES];

正如 Jason 所说,popToRootViewController 必须在没有动画的情况下执行才能正常工作.

感谢 Apple 论坛上的 jpimbert 指出这一点.p>

I have a tabBarController with two tabs, first of which contains an instance of NavigatorController. The navigatorController is initiated with a custom viewController "peersViewController" that list all the network peers on a tableView. Upon selecting a peer, an instance of "FilesListViewController" (which list files in the c: directory) is pushed into the navigationController stack.

In this filesListViewController I have a button to let it navigate to say documents directory. To do this I'd wired the interface to call a gotoDirectory:(NSString*)path method in the rootViewController:

- (void)gotoDirectory:(NSString*)path {
     [[self navigationController] popToRootViewControllerAnimated:YES];
     NSArray *files = [self getFilesFromPeerAtPath:path];
     FilesListViewController *filesVC = [[FilesListViewController alloc] initWithFiles:files];
     [[self navigationController] pushViewController:filesVC animated:YES];
     [filesVC release];
}

However, when I press that button, the navigationController did pop my view to the root view controller, but then the FilesListViewController that I instantiated did not appear. From the log, I know that the custom initWithFiles method was indeed called and network stuffs did happen to get the file names.

Something else is screwy about this. I tried clicking on the second tab and then click back to the first tab, and huala! the file names I needed are there. It looks like the data and the filesListViewController was indeed pushed into the navigatorController stack, but the display was not refreshed but stuck at the screen of rootViewController (peersViewController).

Am I doing anything wrong?

--Ben.

-- Edited like 15 minutes after posting the question. I'd found a workaround, but it bothers me that pop and then push doesn't work.

- (void)gotoDirectory:(NSString*)path {
     PeersListViewController *rootViewController = (PeersListViewController*)[[[self navigationController] viewControllers] objectAtIndex:0];
     [[self navigationController] setViewControllers:[NSArray arrayWithObject:rootViewController]];
     FilesListViewController *filesVC = [[FilesListViewController alloc] initWithFiles:files];
     [[self navigationController] pushViewController:filesVC animated:YES];
     [filesVC release];
}

It doesn't seem like the navigationController should be circumvented this way, and I'd probably have to release all the viewControllers that were in the original stack. This does however work on the iphone 3.0 simulator.

If I'm using this code though, how should the memory release be handled? should I get the original NSArray of viewcontrollers and release everything?

解决方案

The problem and solution to this issue is actually extremely simple.

Calling [self.navigationController popToRootViewControllerAnimated:YES] sets self.navigationController to nil. When you subsequently call [self.navigationController pushViewController:someOtherViewController] you are effectively sending a message to nil, which does nothing.

To workaround, simply set up a local reference to the navigationController and use that instead:

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

As stated by Jason, the popToRootViewController must be performed without animation for this to work correctly.

Thanks go to jpimbert on the Apple forums for pointing this out.

这篇关于UINavigationController popToRootViewController,然后立即推送新视图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-19 00:37