parentViewController 总是导航控制器吗?
Posted
技术标签:
【中文标题】parentViewController 总是导航控制器吗?【英文标题】:Is parentViewController always a Navigation controller? 【发布时间】:2008-10-28 19:48:25 【问题描述】:一周前我对此有点摸不着头脑,现在有了更多可可经验,我觉得我对可能发生的事情有所了解。
我正在制作一个由 UINavigationController 驱动的应用程序。在 AppDelegate 中,我创建了这个类的一个实例,使用“page 1”作为根视图控制器。
UINavigationController *aNavigationController = [[UINavigationController alloc]
initWithRootViewController:page1ViewController];
现在这就是我遇到问题的地方。从“第 1 页”开始,我想使用一个模态视图控制器,它在界面上滑动,然后在用户进行编辑后消失。我在 Page1ViewController 内部使用这样的代码来做到这一点:
[self presentModalViewController:myModalViewController animated:YES];
当模态视图控制器消失时,我希望根据用户在模态视图控制器中输入的内容更改“第 1 页”上的值。所以,我写了一些这样的代码,它驻留在模态视图控制器中:
[self.parentViewController dismissModalViewControllerAnimated:YES];
[self.parentViewController doSomethingPleaseWithSomeData:someData];
没有更新到第 1 页,我花了很长时间才意识到“doSomethingPleaseWithSomeData”消息没有发送到 Page1ViewController,而是发送到导航控制器。
在使用导航控制器时是否总是会出现这种情况?我是否可能配置不正确?有没有一种简单的方法可以访问我想要的视图控制器(在本例中为 Page1ViewController)。
【问题讨论】:
【参考方案1】:我建议使用委托模式来解决您的问题。创建属性
@property (nonatomic, assign) id <MyModalViewDelegate> delegate;
以及相应的协议
@protocol MyModalViewDelegate
@optional
- (void)myModalViewControllerDidFinish:(MyModalViewController *)aModalViewController;
@end
当用户完成您的视图时(例如点击保存按钮),发送此消息:
if ([self.delegate respondsToSelector:@selector(myModalViewControllerDidFinish:)])
[self.delegate myModalViewControllerDidFinish:self];
现在,将委托设置为应该管理整个事情的视图控制器,当视图控制器完成时它会收到通知。请注意,您需要您的视图控制器来关闭模态视图控制器。但是,从逻辑上讲,这是有道理的,因为它是首先呈现模态视图控制器的对象。
这就是 Apple 在 UIImagePickerController 和 UIPersonPickerController 中解决此问题的方法。
【讨论】:
【参考方案2】:有几种方法可以解决这个问题。最简单的可能就是在 myModalViewController 中添加一个 UIViewController 属性,并在呈现之前将其设置为 page1Controller:
myModalViewController.logicalParent = self; //page1Controller
[self presentModalViewController:myModalViewController animated:YES];
只需确保将适当的实例变量@property 和用于logicalParent 的@synthesize 添加到myModalViewController,然后您就可以将数据传回触发模态对话框的ViewController。这也适用于在不同导航级别之间来回传递数据,然后再将它们推送和弹出堆栈。
这样做时要担心的一件重要事情是,如果您不小心,很容易获得保留循环。根据您的具体结构,您可能需要使用分配属性。
【讨论】:
完全符合我的要求,谢谢!我是 Cocoa 的新手,但不是 MVC 的新手。但问题是,作为一名 Java Web 开发人员,我几乎总是忘记“C”中的控制器可以相互交互! 一个很好的答案,但为什么会这样呢?很明显不是模态视图的 parentViewController 是任何逻辑意义上的导航控制器(page1Controller 是要求模态显示的控制器),那么为什么 Cocoa Touch 会这样设置呢? 【参考方案3】:我刚刚遇到了同样的问题。显然,如果您将 UIViewController 嵌入到 NavigationController 中,那么当您从该 UIViewController 以模态方式呈现另一个 UIViewController 时,演示者认为演示者是 NavigationController。也就是说,parentViewController 不正确。
我敢打赌这是一个错误:要么是这样,要么文档似乎不完整。我去问问。
【讨论】:
【参考方案4】:刚刚遇到了同样的问题。我相信这是一个错误。我的情况如下: 按此顺序具有 A、B 和 C 视图控制器的导航层次结构。在 C 上,有一个按钮可以打开一个名为 D 的模式视图控制器。一旦呈现 D,导航控制器就会从其层次结构中删除 C,这是一种可怕的行为。一旦 D 被解除,导航控制器实例化一个新的 C 类型视图控制器并将其推入其层次结构以恢复原始视图控制器。糟糕的。我的解决方案是以这种方式破解导航层次结构(一个非常糟糕的解决方案,但效果很好。使用二维数组,您可以实现堆叠模式):
- (void)presentModalViewController:(UIViewController *)c
[self.navigationHierarchy removeAllObjects];
[self.navigationHierarchy addObjectsFromArray:[navigation viewControllers]];
[navigation setViewControllers:[NSArray array] animated:YES];
[navigation presentModalViewController:c animated:YES];
- (void)dismissModalViewController
[navigation dismissModalViewControllerAnimated:YES];
[navigation setViewControllers:[NSArray arrayWithArray:self.navigationHierarchy] animated:YES];
这两个方法是在我维护主要导航层次结构的地方定义的:应用程序委托。导航和导航层次结构是这样定义的:
NSMutableArray *navigationHierarchy;
UINavigationController *navigation;
【讨论】:
以上是关于parentViewController 总是导航控制器吗?的主要内容,如果未能解决你的问题,请参考以下文章
自动将事件从 ChildViewController 传递到 parentViewController
如何从子视图访问 ParentViewController 方法?
对 ParentViewController 的开始/结束外观转换的不平衡调用
UIViewController 没有带有 UIModalPresentationFormSheet 的 parentViewController?