parentViewController始终是导航控制器吗?

时间:2008-10-28 19:48:26

标签: iphone cocoa-touch

一周前,我对此感到有些不安,现在我的腰带上有一点点可可体验,我觉得我对可能发生的事情有所了解。

我正在创建一个由UINavigationController驱动的应用程序。在AppDelegate中,我创建了这个类的实例,使用“第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,而是发送到导航控制器。

使用导航控制器时总会出现这种情况吗?我是否可能配置不正确的东西?是否有一种简单的方法来获取我想要的View Controller(在本例中为Page1ViewController)。

4 个答案:

答案 0 :(得分:14)

我建议使用委托模式来解决您的问题。创建一个属性

@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中解决这个问题的方法。

答案 1 :(得分:4)

有几种方法可以解决这个问题。最简单的可能只是将一个UIViewController属性添加到myModalViewController中,并在呈现之前将其设置为page1Controller:

myModalViewController.logicalParent = self; //page1Controller
[self presentModalViewController:myModalViewController animated:YES];

只需确保为myModalViewController添加适当的实例变量@property和@synthesize for logicalParent,然后您就可以将数据传递回触发模式对话框的ViewController。这也适用于在推送和弹出堆栈之前在不同级别的导航之间来回传递数据。

在执行此操作时要担心的一件重要事情是,如果您不小心,很容易获得保留循环。根据您的具体构造方式,您可能需要使用assign属性。

答案 2 :(得分:1)

我刚遇到同样的问题。看起来如果你把一个UIViewController嵌入到NavigationController中,那么当你从UIViewController中以模态方式呈现另一个UIViewController时,主持人会认为演示者是NavigationController。换句话说,parentViewController不正确。

我敢打赌这是一个错误:要么是这样,要么文档似乎不完整。我会询问。

答案 3 :(得分:1)

刚遇到同样的问题。我相信这是一个错误。我的方案如下: 具有此顺序的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];
}

这两个方法是在我维护主导航hiererchy的地方定义的:app delegate。导航和导航层次结构以这种方式定义:

NSMutableArray *navigationHierarchy;
UINavigationController *navigation;