子视图控制器在呈现和关闭模态视图后失去委托

Child View Controller loses delegate after Presenting and Dismissing Modal View

我正在使用此代码添加子视图控制器:

MyCustomViewController * overlayView = [[MyCustomViewController alloc] initWithNibName:@"MyCustom" bundle:nil];

UIViewController *parentViewController = self.tabBarController;
[modalView willMoveToParentViewController:parentViewController];

// set the frame for the overlayView
overlayView.view.frame = parentViewController.view.frame;

[parentViewController.view addSubview: overlayView.view];

[parentViewController.view needsUpdateConstraints];
[parentViewController.view layoutIfNeeded];

// Finish adding the overlayView as a Child View Controller
[parentViewController addChildViewController: overlayView];
[overlayView didMoveToParentViewController:parentViewController];

然后在 MyCustomViewController 内点击一个按钮会触发一个模态视图:

MyModalViewController *vc = [[MyModalViewController alloc] initWithNibName:@"DirectEmployerSignup" bundle:nil];

UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:vc];
UIBarButtonItem *button = [[UIBarButtonItem alloc] initWithTitle:@"Close" style:UIBarButtonItemStylePlain target:self action:@selector(closeTheModal:)];
vc.navigationItem.leftBarButtonItem = button;

[self.navigationController presentViewController:navigationController animated:YES completion:nil];

点击 UIBarButtonItem 触发 closeTheModal:

- (void)closeTheModal:(id)sender {
    [self dismissViewControllerAnimated:YES completion:nil];
}

模式关闭后,MyCustomViewController 仍然可见,但视图停止按预期做出反应。 MyCustomViewController 上的 UITextViews 不会触发 MyCustomViewController.m 等中的委托方法

为了清楚起见:我仍然可以点击 MyCustomViewController 上的 UITextFields,并且仍然可以看到按钮在我点击它们时有反应,但是它们未触发其关联 IBActions

如果您对正在发生的事情有任何想法,我们将不胜感激。

附加信息 我添加了一个关闭模态的方法,使用 MyModalViewController 中的 [self.navigationController dismissViewControllerAnimated:YES completion:nil]; 并将 action:@selector() 指向该方法。

MyModalViewController 中的方法触发并关闭了模式,但 MyCustomViewController 仍然没有响应。

po [[[[UIApplication sharedApplication] keyWindow] rootViewController] _printHierarchy] 当我 运行 po [[[[UIApplication sharedApplication] keyWindow] rootViewController] _printHierarchy],在模态视图出现之前,我看到了这个:

<UINavigationController 0x7fc23985b200>, state: appeared, view: <UILayoutContainerView 0x7fc238f3b760>
   | <MyTabBarController 0x7fc23a045400>, state: appeared, view: <UILayoutContainerView 0x7fc238cc7500>
   |    | <MyNavigationController 0x7fc23985a800>, state: appeared, view: <UILayoutContainerView 0x7fc23b0497e0>
   |    |    | <FirstTabViewController 0x7fc238d47650>, state: appeared, view: <UIView 0x7fc23b1318a0>
   |    | <UINavigationController 0x7fc23a0bc000>, state: disappeared, view:  (view not loaded)
   |    |    | <SecondTabViewController 0x7fc238c8da90>, state: disappeared, view:  (view not loaded)
   |    | <UINavigationController 0x7fc23987c800>, state: disappeared, view:  (view not loaded)
   |    |    | <ThirdTabViewController 0x7fc238f77c00>, state: disappeared, view:  (view not loaded)
   |    | <MyCustomViewController 0x7fc238d48e50>, state: appearing, view: <UIView 0x7fc23b086220>

但是...在我关闭模态框并重新运行 po [[[[UIApplication sharedApplication] keyWindow] rootViewController] _printHierarchy] 后,<MyCustomViewController 0x7fc238d48e50> 不见了。

也许问题源于 <MyCustomViewController> 说 "appearing" 而没有说 "appeared"?

我的解决方案 我从

更改为 MyCustomViewController

UIViewController *parentViewController = self.tabBarController;

UIViewController *parentViewController = self.tabBarController.navigationController;

感谢所有提供帮助的人。我会重新审视你的答案,希望下次能把这个效果做得更好。

您需要确保在模态中关闭 navigationController...否则它只是关闭内部控制器(不是它的父级!)并且仍然存在(并拦截您的事件)

- (void)closeTheModal:(id)sender {
    [self.navigationController dismissViewControllerAnimated:YES completion:nil];
}

此问题是由于您的 MyCustomViewController 已从其父控制器中删除所致。届时您的活动将停止传送。

根据您发布的代码,我不能说是什么导致控制器被删除,但您应该能够使用 -[MyCustomViewController removeFromParentViewController]: 中的断点很容易地调试它。您要么是错误地明确删除了它,要么是 UITabBarController 自行删除(可能是由下述问题引起的)。

但是,还有一个大问题:

UITabBarController 是一个容器控制器。控制器的全部意义在于管理其子视图控制器。这也意味着控制器正在管理哪个控制器正在接收外观回调(例如 viewWillAppear:viewDidAppear: 等)。通过添加另一个子视图控制器,您正在做一些不受支持的事情。

例如,当UITabBarController出现时,它只发送viewDidAppear:到它选择的控制器。它不会将 viewDidAppear: 发送到您的附加控制器。

这会导致许多非常有问题的状态,我认为这是您问题的根源。

与其将子控制器直接添加到 UITabBarController,您可以考虑以下层次结构(为选项卡栏控制器和您的自定义控制器引入一个公共父级)。

UIViewController
   |  UITabBarController
   |  MyCustomViewController

您的问题出在这段代码中

MyModalViewController *vc = [[MyModalViewController alloc] initWithNibName:@"DirectEmployerSignup" bundle:nil];
UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:vc];
UIBarButtonItem *button = [[UIBarButtonItem alloc] initWithTitle:@"Close" style:UIBarButtonItemStylePlain target:self action:@selector(closeTheModal:)];
vc.navigationItem.leftBarButtonItem = button;
[self.navigationController presentViewController:navigationController animated:YES completion:nil];

当您声明时,

UIBarButtonItem *button = [[UIBarButtonItem alloc] initWithTitle:@"Close" style:UIBarButtonItemStylePlain target:self action:@selector(closeTheModal:)];
vc.navigationItem.leftBarButtonItem = button;

目标集是 self,正如您在 MyCustomViewController 中声明的那样,自身将是一个 MyCustomViewController 实例。并且可能您已经在同一个 class 中声明了选择器 closeTheModal。因此用 self 释放的实例可能是 MyCustomViewController insatnce.

这样做,

UIBarButtonItem *button = [[UIBarButtonItem alloc] initWithTitle:@"Close" style:UIBarButtonItemStylePlain target:**vc** action:@selector(closeTheModal:)];
vc.navigationItem.leftBarButtonItem = button;

并在 MyModalViewController 中声明选择器 class 并检查。