Short answers
- Compilers use different processes to analysis code. There are a bunch of lectures on colleges how compilers work. So it's quite difficult to give you a correct answer.
- Use what you need. It's quite difficult to asses how much this cost. @escaping and @no-escaping have different use cases.
- I don't see disadvantages. Using weak is a good way to prevent retain cycles and memory leaks.
Explanation
1: So how exactly this compiler works I really don't know. But if you like to get a understanding how compilers generally work read some light weight articles like this one
In my idea the compiler will have a lexical analysis, syntax analysis and semantic analysis. So the compiler will detect if you need an escape or not.
2: Closures is a concept in swift that you "Do stuff when things have done". For more detail have a look in the documentation and here
The following information are based a lot on this article what-do-mean-escaping-and-nonescaping-closures-in-swift
In Swift 1 and 2 closures were @escaping by default. Since Swift 3 closures are @no-escaping.
@no-escaping clousures
When you are passing a closure in function’s arguments, using it before the function’s body gets execute and returns the compiler back. When the function ends, the passed closure goes out of scope and have no more existence in memory.
Simply said, it's comfortable memory handling for the developer because he hasn't to care about anything.
@escaiping closures
For @escaping closures there are two use cases:
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.
From Apple documentation
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.
[...] you can write @escaping before the parameter’s type to
indicate that the closure is allowed to escape.
FYI: Closures marks that an operation is asynchronous and not compellingly on the background thread.
3: I don't see disadvantages to use it. Using weak is a good way to prevent retain cycles and memory leaks. You should ignore the potential costs when you get a stable app. But I repeat: Use what you need. With memory leaks it's a tricky thing and often they are hard to find.
See https://stackoverflow.com/a/34566876/4420355 for a really good answer about delegates and memory leaks. There are a lot of further links in this post too. If you read them you will get a good/better understanding how memory leaks will occur and how to prevent them.
And check this post too, it's a little bit similar to yours https://stackoverflow.com/a/46245943/4420355
Edit to 3
questioner:
I guess i didn't get it right.. so what does it mean "capture", how does it really work behind the scene in terms of unowned self? how the closure use self without owning the object? maybe this question need to be separate to stackoverflow
Inspired by the example of the post Can a local variable's memory be accessed outside its scope?
You rent a hotel room. You check out the next morning, lock the door, but "forget" to give back your key. You steal the key! There is no spare key. So the hotel room is locked. The hotel owner can't rent this room anymore. Now there are a lot of guests which steal the key. Sometime every room is actually free but locked.
With a little bit fantasy the tenant is a closure. He rents the room (creates a references to the room instance). He sleeps there (asynchronous operation). He should give back his key but he doesn't.
In my understanding the closure doesn't owning the object. It's a reference between the closure and a property of an instance.
Apple documentation:
A strong reference cycle can also occur if you assign a closure to a
property of a class instance, and the body of that closure captures
the instance. This capture might occur because the closure’s body
accesses a property of the instance, such as self.someProperty, or
because the closure calls a method on the instance, such as
self.someMethod(). In either case, these accesses cause the closure to
“capture” self, creating a strong reference cycle.
You can resolve that strong cycle with weak
or unowned
. In my opionen the images that apple uses to explain the difference between weak
and unowned
are really good: See Automatic Reference Counting