In a lot of sample, people use closures to pass a function as a parameter :
sum.getSumOf(array: [1,2,3]) { [weak self] sum in
self?.result = sum
print(self?.result as Any)
}
I understand that is done for cycling issues. But what about passing a function rather than a closure ? How make this function "weak" ?
For example:
class Calculator {
let sum = Sum()
var result = 0
// passing a function
func doSum() {
sum.getSumOf(array: [1,2,3], handler: store(sum:))
}
// vs use closure
func doSumWeakSelf() {
sum.getSumOf(array: [1,2,3]) { [weak self] sum in
self?.result = sum
print(self?.result)
}
}
func store(sum:Int){
result = sum
print(result)
}
}
class Sum {
func getSumOf(array:[Int], handler: ((Int)->Void)) {
//step 2
var sum: Int = 0
for value in array {
sum += value
}
handler(sum)
}
}
With everything you have learned so far, you can finally understand what [weak self] means when working with closures in Swift. In Swift, [weak self] prevents closures from causing memory leaks in your application. This is because when you use [weak self], you tell the compiler to create a weak reference to self.
Inferring Type From Context Because the closure is passed as an argument to a method, Swift can infer the types of its parameters and the type of the value it returns from that method. We can omit the return type, the arrow (->), parameters type, and the parentheses around those inputs. scores.filter { score in
In Swift, a closure captures its context. This means it strongly references anything referred to inside of it. If you have a closure that belongs to a class, and you call self inside that closure, you create a strong reference cycle. The closure strongly references to self.
Because the sorting closure is passed as an argument to a method, Swift can infer the types of its parameters and the type of the value it returns. The sorted (by:) method is being called on an array of strings, so its argument must be a function of type (String, String) -> Bool.
First, in your example there is no need for weak
at all. There is no retain loop, since the handler is not escaping. It is executed immediately and released. You shouldn't use weak
in cases where there can not be a retain loop.
Even in escaping cases, there may not always be a retain loop, since the closure may eventually be released. When there is an @escaping
annotation, however, you can only really know this through documentation.
That said, to your specific question, in this example:
func doSum() {
sum.getSumOf(array: [1,2,3], handler: store(sum:))
}
This captures self
(since it's an implicit parameter to store(sum:)
), and it is not possible to make self
weak using this syntax. That's ok in this case, since there is no retain loop, but if there were one, you could not resolve it if you choose to pass a method this way.
AFAIK, there is no built-in solution in Swift that would allow to pass a weak/unowned reference to a function (and I think I've seen this being discussed on Swift proposal forums). For now, you will need to wrap the function inside a closure:
sum.getSumOf(array: [1,2,3]) { [weak self] int in
self?.store(sum: int)
}
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