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?
This means we need to pass a callback function as an argument to greet() function when calling it. The greet() function calls the completion handler right after it has printed “Hello world!” into the console. This executes the completion handler we pass into the greet() function call.
A common application of a closure is the completion handler. It works roughly like this: You're executing a lengthy task in your code, like downloading a file, making a calculation, or waiting for a webservice request.
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.
To store local variable closure completionHandler to global variable 'completionHandlers we using @escaping` keyword! without @escaping keyword someFunctionWithEscapingClosure returns, local variable completionHandler will remove from memory. @escaping is keep that closure in the memory.
Swift Completion Handler Escaping & Non-Escaping:
As Bob Lee explains in his blog post Completion Handlers in Swift with Bob:
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 :
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With