0

I have a predefined function that has a completion param:

func checkNotificationEnabled(_ resultBlock : ((Bool)->())? = nil){
    Bool enabled = false

    ... a big block of code that gets enabled value 
    ...
    ... end block

    resultBlock?(enabled)
}

I need to get the true/false and pass it to another function:

@objc
func isNotificationEnabled(_
    resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock
) -> Void {
    checkNotificationEnabled { (enabled:Bool) in
        resolve(enabled)
    }
}

Got the error: Escaping closure captures non-escaping parameter 'resolve'

How can I pass enabled to resolve ?

Blazej SLEBODA
  • 8,936
  • 7
  • 53
  • 93
Neo.Mxn0
  • 953
  • 2
  • 8
  • 25
  • 1
    Add `@escaping` for the `resolve` parameter: `func isNotificationEnabled(_ resolve: @escaping RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) -> Void` – Yonat Jan 14 '20 at 11:23
  • Ah, I was trying to post an answer and there is a comment already :) Anyways, my answer might help you on 'why' this happens. So I'll leave it as is... – Lokesh SN Jan 14 '20 at 11:33

2 Answers2

0

Presuming RCTPromiseResolveBlock on func isNotificationEnabled to be some block that you're trying to execute with respect to completion of func checkNotificationEnabled, the completion actually 'escapes' (outlives) the scope of the function, and the compiler simply complains that your RCTPromiseResolveBlock may not be alive (in execution) during the completion callback

You'll have to mark @escaping to the 'resolve' parameter to get around this.

You'll definitely get more clarity when you understand what escaping closures are. Have a look at this question: Escaping Closures in Swift

Hope this helps.

Lokesh SN
  • 1,583
  • 7
  • 23
0
  • resolve argument is passed to a function checkNotificationEnabled but is not marked @escaping
  • (Bool)->())? = nil optional is nil by default, so no need to assign nil
  • (Bool)->() this is equal to more readable version Void.

typealias ResultBlock = (Bool) -> Void
func checkNotificationEnabled(_ resultBlock: ResultBlock?) {
    var enabled = false

    ... a big block of code that gets enabled value 
    ...
    ... end block

    resultBlock?(enabled)
}

@objc
func isNotificationEnabled(_
    resolve: @escaping RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) {
    checkNotificationEnabled { enabled in
        resolve(enabled)
    }
}

Escaping closures

A closure is said to escape a function when the closure is passed as an argument to the function, but is called after the function returns. When you declare a function that takes a closure as one of its parameters, you can write @escaping before the parameter’s type to indicate that the closure is allowed to escape.

One way that a closure can escape is by being stored in a variable that is defined outside the function. As an example, many functions that start an asynchronous operation take a closure argument as a completion handler. The function returns after it starts the operation, but the closure isn’t called until the operation is completed—the closure needs to escape, to be called later. source

Blazej SLEBODA
  • 8,936
  • 7
  • 53
  • 93