代码之家  ›  专栏  ›  技术社区  ›  bpapa

ParentViewController是否始终是导航控制器?

  •  7
  • bpapa  · 技术社区  · 16 年前

    一周前我有点抓耳挠腮,现在我的腰带下有了一点可可的感觉,我觉得我对可能发生的事情有了初步的了解。

    我正在制作一个由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页的更新没有发生,我花了很长时间才意识到“DoSomeMingPleaseWithSomeData”消息没有发送到page1viewController,而是导航控制器。

    在使用导航控制器时,是否总是需要这样做?我是否配置不当?有没有一种简单的方法可以找到我想要的视图控制器(在本例中是page1viewcontroller)。

    4 回复  |  直到 14 年前
        1
  •  14
  •   Alex    16 年前

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

    @property (nonatomic, assign) id <MyModalViewDelegate> delegate;
    

    以及相应的协议

    @protocol MyModalViewDelegate
    @optional
        - (void)myModalViewControllerDidFinish:(MyModalViewController *)aModalViewController;
    @end
    

    当用户完成查看后(如点击保存按钮),发送此消息:

    if ([self.delegate respondsToSelector:@selector(myModalViewControllerDidFinish:)])
        [self.delegate myModalViewControllerDidFinish:self];
    

    现在,将委托设置为视图控制器,它应该管理整个事件,当视图控制器完成时,它将得到通知。请注意,您需要视图控制器来关闭模式视图控制器。但是,从逻辑上讲,这是有意义的,因为它首先是呈现模态视图控制器的对象。

    这就是苹果解决这个问题的方法,例如uiImagePickerController和uiPersonPickerController。

        2
  •  4
  •   Louis Gerbarg    16 年前

    有几种方法可以处理这个问题。最简单的方法可能只是将uiviewController属性添加到myModalView控制器中,并在显示它之前将其设置为page1controller:

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

    只要确保将适当的实例变量@property和@synthesis for logicalparent添加到mymodalview控制器,就可以将数据通信回触发模式对话框的viewcontroller。这也适用于在不同级别的导航之间来回传递数据,然后再将它们推送到堆栈上。

    在执行此操作时要担心的一个重要问题是,如果不小心,很容易出现保留循环。根据具体的结构,您可能需要使用分配属性。

        3
  •  1
  •   Michael    14 年前

    我也遇到了同样的问题。显然,如果将uiviewController嵌入到导航控制器中,那么当从该uiviewController以某种方式呈现另一个uiviewController时,演示者认为演示者是导航控制器。换句话说,ParentViewController不正确。

    我敢打赌这是一个bug:要么就是这个,要么文档看起来不完整。我会询问的。

        4
  •  1
  •   zgobolos    14 年前

    只是遇到了同样的问题。我相信这是个虫子。我的场景如下: 按此顺序带有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;