0

I have the following function

static func promptToHandleAutoLink(onEdit: () -> ()) {
    let alert = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
        
    alert.addAction(UIAlertAction(title: "Edit", style: .default) { _ in
        onEdit()
    })

    ...
}

I am getting the compilation error

Escaping closure captures non-escaping parameter 'onEdit'

When I look at the defination of UIAlertAction constructor, it looks like

@available(iOS 8.0, *)
@MainActor open class UIAlertAction : NSObject, NSCopying {

    
    public convenience init(title: String?, style: UIAlertAction.Style, handler: ((UIAlertAction) -> Void)? = nil)
}

As, there is no @escaping keyword for handler, I thought handler suppose to be a non-escaping closure.

If that is so, why I am getting such compiler error?

I know I can solve this issue by simply adding @escaping keyword on onEdit.

static func promptToHandleAutoLink(onEdit: @escaping () -> ()) {
    let alert = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
        
    alert.addAction(UIAlertAction(title: "Edit", style: .default) { _ in
        onEdit()
    })

    ...
}

But still, I would like to understand, the reason I am getting such compiler error, because UIAlertAction's handler seems like a non-escaping closure.

Thanks.

Cheok Yan Cheng
  • 47,586
  • 132
  • 466
  • 875
  • If optional, you can skip the `@escaping`. In this case it's escaping, because the method will reach its ends, before the closure gets called by a user action. – Larme Oct 11 '22 at 10:48

1 Answers1

1

Whenever you pass a closure to your function and this closure will be called at some later point in the future, i.e. after the function returns, you have to mark it as an @escaping closure. In your particular case, the closure is stored in memory because you called it in the completion parameter of the alert.addAction method, i.e. it will be called whenever the user clicks on the corresponding alert view's button, so it has to "escape" the function scope and live somewhere else in the memory.

birkoof
  • 173
  • 8
  • 3
    The closure to `UIAlertAction` is escaping because `handler:` is an _optional_ closure, which automatically makes it escaping even though there's no explicit `@escape` here. That's what confused OP and what needs explanation. – DarkDust Oct 11 '22 at 11:16