I tried to dig on this subject as much as i could, but still i've a few things that wasn't settled down in my head and i will be grateful to get clarification about them.. so i made a few questions..
- How the compiler know that i've to add @escaping on background thread, and by that to force me to use it?
- Is there a cost for using @escaping? if not.. Why not to mark always? What could went wrong if i mark closure with @escaping even if i don't really need it? When i was trying to do so.. there were no problems on my code and the result with or without @escaping remained the same.
- What is the cost of using capture list [weak self] [unowned self]? I know that it making a copy of that object, so i guess temporarily it take more memory, but in the end of that use that copy will removed from memory.. so, there is more disadvantages of using it?
Short answers
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
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
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:
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:
You can resolve that strong cycle with
weak
orunowned
. In my opionen the images that apple uses to explain the difference betweenweak
andunowned
are really good: See Automatic Reference Counting