UIViewController accepts non-escaping closure?

Just occurred to me today that UIKit methods like present() or dismiss() on view controllers now accept non-escaping closures. Is this a bug in documentation/SDK?

open func present(_ viewControllerToPresent: UIViewController, animated flag: Bool, completion: (() -> Void)? = nil)

open func dismiss(animated flag: Bool, completion: (() -> Void)? = nil)

See: dismiss(animated:completion:) | Apple Developer Documentation

Optional closures are always escaping.

3 Likes

Ah that's right! Thanks.

1 Like

Which is kind of a bug.... Could be worked around by either a longer:

open func present(_ vc: UIViewController, animated: Bool, completion: @escaping () -> Void) {
    ...
}
open func present(_ vc: UIViewController, animated: Bool) {
    present(vc, animated: animated) {}
}
open func dismiss(animated: Bool, completion: @escaping () -> Void) {
    ...
}
open func dismiss(animated: Bool, completion: @escaping () -> Void) {
    dismiss(animated: animated) {}
}

or a shorter:

open func present(_ vc: UIViewController, animated: Bool, completion: @escaping () -> Void = {}) {
    ...
}
open func dismiss(animated: Bool, completion: @escaping () -> Void = {}) {
    ...
}

Sure, but in this case they should be escaping.

Ah, yep, you are right. I meant situations when closures are turned from nonescaping to escaping by virtue of being optional.

Yes, your workarounds work when you want the closure to be nonescaping. Hopefully someday we will have nonescaping for all argument types.