I'm aware of the fact that closure
can create retain cycles
if it is assigned to a property of a class and instance properties of the class are used inside of the closure. But
1) what about the closure is not assigned to the class property but passed as parameter to a singleton's class method ?
2) How the memory is managed in this case ?
In a method of my controller (UIViewController) I have something like:
MySingleton.classMethod(parameters ..., completion: { () -> Void in
/**
doing stuff here
*/
})
If You are not assigning the closure to a property, but just passing it to a function You need to consider if the closure will be escaping or noescape. In Swift 3 by default all closures passed to functions are non-escaping.
Here is a little bit more info on the matter:
"noescape" - the passed closure is invoked before the return of the function
"escaping" - If a closure is passed as an argument to a function and it is invoked after the function returns, the closure is escaping.
Simple explanation : We need to mark closure as escaping when we pass it to a function and the closure will be called after this function returns.
General rule is when the closure is escaping You need to use capture list to prevent retain cycles.
Example
Additional info:
One weird thing is that optional closures are treated as escaping. And when we explicitly add escaping keyword, there is a compile error -escaping attribute only applies to function types.
See the below links for more info.
https://bugs.swift.org/browse/SR-2053
https://stackoverflow.com/a/39619298/5388473
https://stackoverflow.com/a/39846519/5388473
Update
The idea of using weak or unowned in the capture lists of escaping closures is that essentially We don't know what will happen with the passed escaping closure, it may be called sometime later from another function or it may be stored in some object, which may lead to a strong retain cycle.
weak vs unowned vs strong capture
For more detailed information check Apple ARC docs.
From Apple docs:
Keep in mind that the weak approach will add a boiler plate to the code and will be a little bit more slow, because ARC will add code for setting the weak variables to nil on their deallocation. It is a good practice to follow the rules stated above, when choosing weak or unowned.