如何在没有委托的情况下以模态方式呈现 ViewController,然后在 ViewController 被解除后运行回调函数/块?
Posted
技术标签:
【中文标题】如何在没有委托的情况下以模态方式呈现 ViewController,然后在 ViewController 被解除后运行回调函数/块?【英文标题】:How to modally present a ViewController, and then the run a callback function / block after the ViewController has been dismissed, without Delegate? 【发布时间】:2016-06-01 02:30:44 【问题描述】:我只是知道self.presentViewController(childVc, animated: true, completion: )
中的完成块是在子视图控制器完成动画以在屏幕上显示 后调用的。我实际上想运行一段代码,在子视图控制器的动画完成动画后显示为 dismissed。我该怎么做,最好避免使用委托来做到这一点?
编辑:我从呈现的(子)视图控制器中调用它,如下所示:self.presentingViewController.dismissViewControllerAnimated (true)
,但问题是子视图控制器可以从任意页面呈现,并且在孩子被解雇后,父(呈现)视图控制器必须做不同的事情。如果我在孩子中实现回调,我不能与调用它的不同父母做不同的事情。
例如,如果我在新闻屏幕中将登录表单称为模态,则在登录表单关闭后,我想在之后显示评论部分。但是如果登录表单从产品屏幕模态显示,我想在之后显示用户的购物车和购物车中的产品。如果没有委托就无法做到这一点,我仍然对委托解决方案感兴趣。
【问题讨论】:
【参考方案1】:您可以向您的ChildVC
添加一个属性来存储回调闭包,并在您呈现子视图控制器时设置它。当子视图控制器关闭自己时,它可以调用完成处理程序:
class ChildVC: UIViewController
var completionHandler : ((childVC:ChildVC) -> Void)?
func dismiss()
self.dismissViewControllerAnimated(true)
self.completionHandler?(childVC:self)
您在呈现 ChildVC 实例时提供完成处理程序:
let completionHandler:(ChildVC)->Void = childVC in
print("completed for \(childVC)")
childVC.completionHandler=completionHandler
self.presentViewController(childVC, animated: true, completion: nil)
【讨论】:
太棒了,您甚至提供了在完成块上呈现的 childVC 的返回值。谢谢! 在self.dismissViewControllerAnimated(true)中,self可能为nil,completionHandler也可能为nil。您需要在上层闭包(例如在dismiss方法级别)中引用completionHandler并在回调块中使用它【参考方案2】:使用dismissViewControllerAnimated
API,它接受一个完成块。
self.dismissViewControllerAnimated(true)
/* Do callback stuff here*/
【讨论】:
我从呈现的(子)视图控制器中调用它,如下所示:self.presentingViewController.dismissViewControllerAnimated (true)
,但问题是子视图控制器可以从任意页面呈现,并且在孩子被解雇后,父(呈现)视图控制器必须做不同的事情。如果我在孩子中实现回调,我不能与调用它的不同父母做不同的事情。
例如,如果我在新闻屏幕中调用登录表单作为模态,在登录表单关闭后,我想在之后显示评论部分。但是如果登录表单从产品屏幕模态显示,我想在之后显示用户的购物车和购物车中的产品。
您需要将回调闭包作为属性提供给 childVC
@Paulw11 哦,没想到!在完全成熟的委托和根本不使用委托的简单性(和复杂性)之间进行了很好的权衡。谢谢!我认为您的答案是目前最实用的。顺便说一句,我认为您需要发表评论作为答案。 :D【参考方案3】:
您可以像 @property(nonatomic,copy)void (^onDimissed)();
那样在呈现的 ViewController 中创建一个回调块,然后在呈现的视图控制器调用 [self dismissViewControllerAnimated:YES completion:^
if (self.onDismissed)
self.onDismissed();
];
所以你可以返回块中的任何参数
别忘了做这个
SomeController *ctr = [[UIViewController alloc] init];
ctr.onDimissed = ^
//some your implementation
;
【讨论】:
谢谢,这太棒了!你有没有机会帮我把它翻译成swift?谢谢! 类似class PresentedViewController: UIViewController var onDismissed : (() -> Void)? func dismissPresented() -> Void self.dismissViewControllerAnimated(true) if self.onDismissed != nil self.onDismissed!() let presented = PresentedViewController(); presented.onDismissed = () -> Void in //your implimentation
【参考方案4】:
如果你使用self.presentingViewController.dismissViewControllerAnimated (true)
这个返回nil为什么意味着它不支持所有的操作系统,所以只需使用下面的代码,
self.dismissViewControllerAnimated(true, completion:
//Put your code
);
如果您关闭ViewController
,您可以调用任何函数,将您的代码放入完成处理程序中。
希望对你有帮助
【讨论】:
不,我的意思是,我不包括块内的实现,因为它与我的问题无关。我只是说block里面的代码是在child view动画展示完成之后调用的,这不是我想要的。我希望在子视图动画关闭完成后调用该块。 :)以上是关于如何在没有委托的情况下以模态方式呈现 ViewController,然后在 ViewController 被解除后运行回调函数/块?的主要内容,如果未能解决你的问题,请参考以下文章
如何在一种情况下推送视图控制器,但在另一种情况下以模态方式呈现它?
如何在应用程序委托iOS10 Objective C中的applicationWillEnterForeground方法中以模态方式呈现UIViewController