如何在没有委托的情况下以模态方式呈现 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

从当前模态的委托中呈现 UIAlertView

使用故事板从应用程序委托呈现模态视图控制器

scrollViewDidScroll 没有被调用(我设置了委托!)

有没有办法在默认情况下以折叠模式呈现 Loopback 4“/explorer”