`UIViewController.present` 立即调用完成处理程序

`UIViewController.present` completion handler being called immediately

我正在使用 Xcode 10 Beta 6,所以这可能只是一个错误。


我正在尝试将视图控制器 (colorPickerController) 呈现为弹出窗口。在该视图控制器中,我将能够设置一些属性,我想在弹出窗口关闭后读取这些属性。

代码如下:

在第 93...97 行中,我定义了一个完成处理程序。
在第 99 行中,我以模态方式呈现 colorPickerController,包括完成处理程序。


当运行 颜色选择器控制器的代码成功显示在弹出窗口中时。但是当我在弹出窗口外点击(关闭它)时,没有调用回调。

我想也许 UIPopoverPresentationController 不会关闭 "normally",所以我尝试通过在 popoverPresentationControllerShouldDismissPopover 中调用 dismiss 手动关闭弹出窗口(第 110 行)。

现在这仍然没有用,所以我设置了一个断点,如图所示,以检查委托方法是否被调用。
那时我注意到,当 运行 应用程序时,完成处理程序会在弹出窗口出现时立即调用,而不是在它关闭时调用。
在到达断点之前,我正在控制台中记录 Completion handler was called.

这怎么可能?

@TylerTheCompiler 是正确的,你传递的完成在动画完成后运行。为了完成您想要的,这是我的建议:

1) 子class UIViewController 并创建自定义类型。

2) 添加一个 属性 到新的 class 类型:

var functionToFinish: (() -> Void)

3) 将更新颜色的定义更改为:

let updateColor: (() -> Void) = ...

3a) 为 ...

插入剩余的函数

4) 在第 98 行写:

colorPickerController.functionToFinish = updateColor

5) 现在,在 subclassed 控制器中,您可以从 viewDidDisappear 事件中调用该函数

您的代码在您的问题中的方式,您的 updateColor 闭包仅在 演示 动画完成时被调用,而不是在您呈现的视图控制器是完成所有需要做的事情。

请参阅 UIViewController.present(_:animated:completion:) 的文档: https://developer.apple.com/documentation/uikit/uiviewcontroller/1621380-present

completion

The block to execute after the presentation finishes. This block has no return value and takes no parameters. You may specify nil for this parameter.

注意 "after the presentation finishes"(强调我的)。这意味着闭包将在从屏幕底部开始动画显示新视图控制器的 0.2 秒后立即执行(或者无论花费多长时间,如果您正在做一些花哨的话,以任何方式)自定义演示动画)。

要在你的新视图控制器完成它需要做的任何事情时得到回调,子类化 UIViewController(称之为 ColorPickerViewController),并使用某种委托来通知您当前的视图控制器关闭颜色选择器视图控制器(并且大概告诉它选择了什么颜色)。