使用另一个 UINavigationController 推送视图控制器

Posted

技术标签:

【中文标题】使用另一个 UINavigationController 推送视图控制器【英文标题】:Pushing a View Controller using another UINavigationController 【发布时间】:2013-07-04 16:15:07 【问题描述】:

这就是我的应用的样子。我对 UINavigationController 进行了子类化,当您点击类似于导航栏的按钮时,MenuViewController 会滑出。如何将我的 VC1、VC2、VC3 之一从 UITableViewController 菜单内的 didSelectRow 推送到 ContentViewController 中?

 -> 滑动视图控制器
                 / \
            集装箱集装箱
                | |
        菜单视图控制器内容视图控制器
                | |
     UITableViewController 子类 UINavigationController
                                  | | | |
                                 VC1 VC2 VC3 VC4

通常我会执行类似下一个代码的操作,但在上述情况下,如果我不在同一个 UINavigationController 中,我不确定如何推送新的视图控制器。

NSString * storyboardName = @"MainStoryboard_iPhone";
NSString * viewControllerID = @"ViewID";
UIStoryboard * storyboard = [UIStoryboard storyboardWithName:storyboardName bundle:nil];
MyViewController * controller = (MyViewController *)[storyboard instantiateViewControllerWithIdentifier:viewControllerID];
[? presentViewController:controller animated:YES completion:nil];

编辑:

可行的解决方案,但我不确定这是否是一个好方法。我已经使用单例来保存我的导航控制器并在以后使用它。

在我的 ContentViewController 中:

[DataManager sharedDataManager].navController = self.navigationController;

在 MenuViewController 我的 didSelectRow 中:

[[DataManager sharedDataManager].navController presentViewController:controller animated:YES completion:nil];

【问题讨论】:

【参考方案1】:

您不希望MenuViewController 了解视图控制器层次结构中除自身及其子级之外的任何内容。您有两种选择可以实现这种良好的设计。

1。使用委托

首先,您需要一个MenuViewControllerDelegate,例如menuViewController:didSelectOption:。当菜单中发生某些事情时,MenuViewController 将向其委托对象发送适当的委托消息。

现在要侦听该委托消息,您将需要一个符合 MenuViewControllerDelegate 并将 MenuViewController 的委托设置为自身的控制器对象(可以是视图控制器或只是普通的 NSObject)。然后,此控制器对象将处理 MenuViewController 可能发送的任何委托消息,例如选择菜单选项时,将新的视图控制器推送到 ContentViewController

2。发布通知

这是两者中更脆弱的一个。如果你的视图控制器层次结构中有很多东西需要知道菜单中什么时候发生,你会使用通知。

所以MenuViewController 会发布一个通知,可能命名为MenuViewControllerDidSelectOptionNotification,然后注册该通知的任何感兴趣的接收者都会收到通知并做他们的事情。

【讨论】:

我采取了代表的方式.. 当然,还有后续 :) :) ***.com/questions/17503798/…【参考方案2】:

在您的 App Delegate 中(或响应您的编辑,任何持久的单例都可以工作,是的),创建属性来保存您的 View Controller 实例。

@property (nonatomic, strong) MenuViewController *menuViewController;

...等你所有的vc。

当您稍后初始化它们时,请在 App 委托上设置此属性以保存 VC。

MenuViewController *menuVC = [[MenuViewController alloc] init];

AppDelegate *appDel = [[UIApplication sharedApplication] delegate];
appDel.menuViewController = menuVC;

现在您可以在需要展示的任何时候获取此实例。您还可以在 menuViewController 上设置要保留在内存中的任何属性。

注意:要成为一个良好的记忆公民。编写 didReceiveMemoryWarning 方法以在 VC 再次可见时释放您可以轻松重新加载的任何内容,这样您就不会因为一次在内存中保存太多内容而导致应用程序崩溃。

【讨论】:

【参考方案3】:

您应该有一个类(可能是应用程序委托)来创建您的容器结构。它可以访问创建的视图控制器。您的表格视图控制器和导航控制器最初可能并不同时存在,但最初创建所有内容的类应该通过将导航控制器或内容视图控制器的引用传递给表格视图控制器或菜单视图来“构建结构之间的桥梁”控制器。该引用应该存储在一个属性中,并允许您干净地呈现您的视图控制器。

这种设置比通过parentViewController 或类似链接更可取,因为这会导致您以不透明的方式将您绑定到特定结构。


或者,在您的故事板中,您可以添加一个IBOutlet 属性并直接在那里建立连接(如果所有视图控制器都是在加载故事板时预先创建的)。

【讨论】:

嗯,我使用界面构建器创建容器,并使用单例存储对导航控制器的属性引用。我猜你的建议差不多是这样吧? 这是一个可行的选项。只要你不滥用DataManager 并且让它做得太多(就像名字暗示你会让它做得太多)那么它应该会很好地工作。 所有容器控制器都在同一个 XIB / Storyboard 中吗? 是的。上图是我的 StoryBoard 方案

以上是关于使用另一个 UINavigationController 推送视图控制器的主要内容,如果未能解决你的问题,请参考以下文章

UITabBarNavigationController 中的 UINavigationController 不加载表数据

功能差异,UINavigationController vs Only Storyboard Segue

在 UINavigationController 中设置自定义导航栏类

在 UINavigationController 中设置自定义导航栏类

UINavigationController -> UIViewController -> UIView -> UITableViewController?

用动画隐藏导航控制器和标签栏控制器