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 ?
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.
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
Related
I created a protocol with a function definition that has a callback function parameter.
But when I try to use the callback in a class that implements the protocol, I get the error:
Closure use of non-escaping parameter 'callBack' may allow it to escape
The fix adds the #escaping flag to the function definition, but then it's no longer confirms to the function definition in the protocol.
This is the function I pass as call back:
private func handleSignUpRes(result:Bool, msg:String, uData:UserData){
if(result == false && (currVC != nil)){
Utilities.ShowAlert(title: "Error", msg: msg, vc: currVC!)
}
else if(result == true){
}
}
You need to pass in a closure that does not escape.
Escaping closures are closures that have the possibility of executing after a function returns.
Rewrite your closure to ensure that it cannot return a value after the function returns.
Unfortunately, without seeing the closure, I cannot tell you why the closure is escaping.
When you post the closure, I will edit my answer.
I need to call a swift function from objective-c. This needs to have a callback (that will be executed from obj-c)
#objc public func getTokens(forAuthentificationCode auth_code : String, completion: ()->()? )
I get "Method cannot be marked #objc because the parameter..."
How to make a function with a completion block that can be used from objective-c?
You declared the completion parameter as ()->()?, which translates to a closure with no parameters and that returns a Void?. Objective-C supports optionals only for class arguments, thus the completion block is not Objective-C compatible.
I think however that you intended to declare the whole closure as optional, in order to allow callers to pass nil, in that case you need to wrap the closure definition into another set of parentheses: completion: (() -> Void)?. I changed the return type from () to Void for better readability, as Void is just an alias for ().
I am trying to understand 'Closure' of Swift more precisely.
But #escaping and Completion Handler are too difficult to understand
I searched many Swift postings and official documents, but I felt it was still not enough.
This is the code example of official documents
var completionHandlers: [()->Void] = []
func someFunctionWithEscapingClosure(completionHandler: #escaping ()->Void){
completionHandlers.append(completionHandler)
}
func someFunctionWithNoneescapingClosure(closure: ()->Void){
closure()
}
class SomeClass{
var x:Int = 10
func doSomething(){
someFunctionWithEscapingClosure {
self.x = 100
//not excute yet
}
someFunctionWithNoneescapingClosure {
x = 200
}
}
}
let instance = SomeClass()
instance.doSomething()
print(instance.x)
completionHandlers.first?()
print(instance.x)
I heard that there are two ways and reasons using #escaping
First is for storing a closure, second is for Async operating purposes.
The following are my questions:
First, if doSomething executes then someFunctionWithEscapingClosure will executing with closure parameter and that closure will be saved in global variable array.
I think that closure is {self.x = 100}
How self in {self.x = 100} that saved in global variable completionHandlers can connect to instance that object of SomeClass ?
Second, I understanding someFunctionWithEscapingClosure like this.
To store local variable closure completionHandler to global variable 'completionHandlerswe using#escaping` keyword!
without #escaping keyword someFunctionWithEscapingClosure returns, local variable completionHandler will remove from memory
#escaping is keep that closure in the memory
Is this right?
Lastly, I just wonder about the existence of this grammar.
Maybe this is a very rudimentary question.
If we want some function to execute after some specific function. Why don't we just call some function after a specific function call?
What are the differences between using the above pattern and using an escaping callback function?
Swift Completion Handler Escaping & Non-Escaping:
Assume the user is updating an app while using it. You definitely want
to notify the user when it is done. You possibly want to pop up a box
that says, “Congratulations, now, you may fully enjoy!”
So, how do you run a block of code only after the download has been
completed? Further, how do you animate certain objects only after a
view controller has been moved to the next? Well, we are going to find
out how to design one like a boss.
Based on my expansive vocabulary list, completion handlers stand for
Do stuff when things have been done
Bob’s post provides clarity about completion handlers (from a developer point of view it exactly defines what we need to understand).
#escaping closures:
When one passes a closure in function arguments, using it after the function’s body gets executed and returns the compiler back. When the function ends, the scope of the passed closure exist and have existence in memory, till the closure gets executed.
There are several ways to escaping the closure in containing function:
Storage: When you need to store the closure in the global variable, property or any other storage that exist in the memory past of the calling function get executed and return the compiler back.
Asynchronous execution: When you are executing the closure asynchronously on despatch queue, the queue will hold the closure in memory for you, can be used in future. In this case you have no idea when the closure will get executed.
When you try to use the closure in these scenarios the Swift compiler will show the error:
For more clarity about this topic you can check out this post on Medium.
Adding one more points , which every ios developer needs to understand :
Escaping Closure : An escaping closure is a closure that’s called after the function it was passed to returns. In other words,
it outlives the function it was passed to.
Non-escaping closure : A closure that’s called within the function it was passed into, i.e. before it returns.
Here's a small class of examples I use to remind myself how #escaping works.
class EscapingExamples: NSObject {
var closure: (() -> Void)?
func storageExample(with completion: (() -> Void)) {
//This will produce a compile-time error because `closure` is outside the scope of this
//function - it's a class-instance level variable - and so it could be called by any other method at
//any time, even after this function has completed. We need to tell `completion` that it may remain in memory, i.e. `escape` the scope of this
//function.
closure = completion
//Run some function that may call `closure` at some point, but not necessary for the error to show up.
//runOperation()
}
func asyncExample(with completion: (() -> Void)) {
//This will produce a compile-time error because the completion closure may be called at any time
//due to the async nature of the call which precedes/encloses it. We need to tell `completion` that it should
//stay in memory, i.e.`escape` the scope of this function.
DispatchQueue.global().async {
completion()
}
}
func asyncExample2(with completion: (() -> Void)) {
//The same as the above method - the compiler sees the `#escaping` nature of the
//closure required by `runAsyncTask()` and tells us we need to allow our own completion
//closure to be #escaping too. `runAsyncTask`'s completion block will be retained in memory until
//it is executed, so our completion closure must explicitly do the same.
runAsyncTask {
completion()
}
}
func runAsyncTask(completion: #escaping (() -> Void)) {
DispatchQueue.global().async {
completion()
}
}
}
/*the long story short is that #escaping means that don't terminate the function life time until the #escaping closure has finished execution in the opposite of nonEscaping closure the function can be terminated before the closure finishes execution Ex:
*/
func fillData(completion: #escaping: () -> Void){
/// toDo
completion()
}
//___________________________
//The call for this function can be in either way's #escaping or nonEscaping :
fillData{
/// toDo
}
/* again the deference between the two is that the function can be terminated before finish of execution nonEscaping closure in the other hand the #escaping closure guarantees that the function execution will not be terminated before the end of #escaping closure execution. Hope that helps ***#(NOTE THAT THE CLOSURE CAN BE OF ANY SWIFT DATA TYPE EVEN IT CAN BE TYPEALIAS)*/
I have read a lot of material on stack overflow and I just cannot figure this one out:
I have been this line of code from an online source for hours and I just don't know why the closure that is being passed into a function is escaping, here is the code:
func composeFunction(functionA: #escaping (Int) -> String, functionB: #escaping (String) -> String) -> ((Int) -> String) {
return {
number in
functionB(functionA(number))
}
}
From apple's documentation, closures are escaping when:
1) Asynchronous operation that runs on a background thread
2) The closure is interactive with properties outside of it's scope (using self)
But I don't see those are happening, many help will be appreciated!
Thanks!
your func composeFunction returns a ((Int) -> (String)) and that is exactly a closure. Of course now this means functionA and functionB are going to be escaping because we don't know when and where this closure will be called. Moreover, this is because it needs to know if it should keep the reference to the objects passed in / being manipulated. For example, if all your closure parameters had (() -> Void) instead and you also returned (() -> Void) then it would not need to be escaping.
{
number in
functionB(functionA(number))
}
is a closure. Returning it causes both functionB and functionA to escape, because it becomes unknown at what point this closure will be called or deallocated.
This is different from just return functionB(functionA(number)), which causes the immediate invocation of both of those functions, and causes them to never escape the composeFunction context.
I have come across this code:
class WebServerTests: XCTestCase {
let webServer: GCDWebServer = GCDWebServer()
var webServerBase: String!
/// Setup a basic web server that binds to a random port and that has one default handler on /hello
private func setupWebServer() {
webServer.addHandlerForMethod("GET", path: "/hello", requestClass: GCDWebServerRequest.self) { (request) -> GCDWebServerResponse! in
return GCDWebServerDataResponse(HTML: "<html><body><p>Hello World</p></body></html>")
}
I am confused by the webServer.addHandlerForMethod part. It seems to me it is already a complete function call (webServer.addHandlerForMethod("GET", path: "/hello", requestClass: GCDWebServerRequest.self)). Therefore I do not understand why it is followed by a closure ( {(request) -> ... )
EDIT: Clarify what I do not understand
According to the documentation on https://github.com/swisspol/GCDWebServer, the function signature in obj-c is:
[webServer addDefaultHandlerForMethod:#"GET"
requestClass:[GCDWebServerRequest class]
asyncProcessBlock:^(GCDWebServerRequest* request, GCDWebServerCompletionBlock completionBlock) {
Therefore I expect its swift counterpart will be called somewhat like this:
webServer.addHandlerForMethod("GET", path: "/hello", requestClass: GCDWebServerRequest.self, { (request) -> GCDWebServerResponse! in
return GCDWebServerDataResponse(HTML: "<html><body><p>Hello World</p></body></html>")
})
i.e. the handling of the incoming request is passed as the third parameter. But since the closure comes after the closing ')', it does not look like part of the function call at all.
Why the function signature is mapped from obj-c to swift this way?
In Swift, you can use this syntax if the last argument to a function is a closure. Here's the example from the Swift language guide section about closures (scroll down to Trailing Closures):
func someFunctionThatTakesAClosure(closure: () -> ()) {
// function body goes here
}
// here's how you call this function without using a trailing closure:
someFunctionThatTakesAClosure({
// closure's body goes here
})
// here's how you call this function with a trailing closure instead:
someFunctionThatTakesAClosure() {
// trailing closure's body goes here
}
And then there's also this note:
If a closure expression is provided as the function’s only argument and you provide that expression as a trailing closure, you do not need to write a pair of parentheses () after the function’s name when you call the function.
This means it's also legal to write this:
someFunctionThatTakesAClosure {
// closure body
}
… which helps provide a nice meta-programming syntax. For example:
let lock = NSLock()
func locked(closure: () -> ()) {
lock.lock();
closure()
lock.unlock();
}
locked {
NSLog("Hello, world!")
}
The closure is where the handling of the incoming request is done. It tells the server to run the closure's code when a GET method that requests /hello path comes.
In the code you posted code in the closure creates a response that the server returns.