从模态视图或推送视图调用父方法到presentingViewController

Posted

技术标签:

【中文标题】从模态视图或推送视图调用父方法到presentingViewController【英文标题】:Calling parent method from a modal or push view to presentingViewController 【发布时间】:2014-03-01 21:43:43 【问题描述】:

我有一个 UINavigationGroup 和一个名为 MainViewController 的根视图控制器。在这个MainViewController 中,我将另一个UINavigationController 作为模态调用,如下所示:

- (IBAction)didTapButton:(id)sender 
    UINavigationController * someViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"someNavigationController"];
    [self.navigationController presentViewController:someViewController animated:YES completion:nil];

在这个someNavigationController 中,用户正在经历一些过程,所以导航控制器被一些UIViewControllers 推送。用户完成该过程后,在最后一个名为finalStepViewControllerUIViewController 中,我将关闭模式如下:

[self dismissViewControllerAnimated:YES completion:nil];

模态确实被解除了,用户又回到了最初的MainViewController。 但是,我想将另一个UIViewController 推送到MainViewController 的 NavigationController(例如:表示用户成功完成该过程的视图)。最好在模态被解除之前。

我尝试了以下方法:

1.使用presentingViewController

UIViewController * successViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"successViewController"];
[self.presentingViewController.navigationController successViewController animated:YES];

结果:没有错误,但也没有发生任何事情。

2。委托/协议

MainViewController.h 中导入finalStepViewController.h 并附加<finalStepViewControllerDelegate>MainViewController.m 内部添加了一个名为parentMethodThatChildCanCall 的方法,可以从finalStepViewController.m 调用

将以下内容添加到finalStepViewController.h

@protocol finalStepViewControllerDelegate <NSObject> -(void)parentMethodThatChildCanCall; @end @property (assign) id &lt;finalStepViewControllerDelegate&gt; delegate; 和模型中的@synthesize delegate;

将上述didTapButtonIBAction 中的delegate 属性设置为someViewController 为self。这显示了一个通知错误:Assigning to id&lt;UINavigationControllerDelegate&gt;' from incompatible type UIViewController *const __strong' 最后在关闭模式之前调用[self.delegate parentMethodThatChildCanCall]

结果:除了通知错误,没有失败但没有任何反应,因为没有调用parentMethodThatChildCanCall

知道我做错了什么/我应该做什么吗?这是我做 Objective-C 的第二周,大多数时候我不知道我在做什么,所以任何帮助/代码都将不胜感激!

谢谢。

【问题讨论】:

【参考方案1】:

使用NSNotificationCenter 可以更轻松地实现这一目标。

在您的MainViewController-viewDidLoad 中添加以下代码

  typeof(self) __weak wself = self;
  [[NSNotificationCenter defaultCenter] addObserverForName:@"successfullActionName"
                                                    object:nil
                                                     queue:[NSOperationQueue mainQueue]
                                                usingBlock:^(NSNotification *note) 
                                                  SuccessViewController *viewController; // instantiate it properly
                                                  [wself.navigationController pushViewController:viewController animated:NO];
                                                ];

在 dealloc 时从 NSNotificationCenter 中移除你的控制器

- (void)dealloc 
  [[NSNotificationCenter defaultCenter] removeObserver:self];

FinalStepViewController 中,在关闭发布通知之前关闭视图控制器的操作

- (IBAction)buttonTapped:(id)sender 
  [[NSNotificationCenter defaultCenter] postNotificationName:@"successfullActionName" object:nil];
  [self dismissViewControllerAnimated:YES completion:nil];

这个例子非常粗略,并不理想,你应该为你的通知名称使用常量,并且在某些情况下存储NSNotificationCenter返回的观察者以删除特定的。

-- 编辑 我还想提一下addObserverForName:object:queue:usingBlock: 方法实际上将观察者作为id 类型对象返回。您需要将对它的引用作为 iVar 存储在您的类中,并在调用 dealloc 方法时将其从 NSNotificationCenter 中删除,否则观察者将永远不会被释放。

【讨论】:

这行得通,感谢您的快速回答。您能否详细说明/提供有关您上一条评论的说明? 您应该创建具有不言自明名称的静态常量,并使用它们代替 NSStrings 作为 notificationName。例如,在您的情况下,您可能创建了一个常量static NSString *const MYSuccessfullActionNotification = @"MYSuccessfullActionNotification"; 并将常量值传递给[[NSNotificationCenter defaultCenter] postNotificationName:MYSuccessfullActionNotification object:nil];。常量基本上可以帮助您避免拼写错误。

以上是关于从模态视图或推送视图调用父方法到presentingViewController的主要内容,如果未能解决你的问题,请参考以下文章

在模态视图被解除后,父视图控制器中是不是有一个委托被调用?

iphone - 将子视图添加到窗口后无法推送模态视图?

使用委托将数据从模态视图传递到父视图(在情节提要中使用 segue)

从模态视图控制器推送/弹出到另一个视图控制器(包括图片)

如何从模态视图推送 UIViewController

我可以从另一个模态视图控制器中推送模态视图控制器吗?