Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing a function vs a closure "weak self" as parameter in swift

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)
    }

}
like image 966
Anthony Avatar asked Oct 15 '19 19:10

Anthony


People also ask

What does [weak self] mean when working with closures in Swift?

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.

How do you infer the type of a closure in Swift?

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

What is a strong reference cycle in swift closure?

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.

What is the argument to the sort method in Swift?

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.


2 Answers

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.

like image 134
Rob Napier Avatar answered Oct 12 '22 14:10

Rob Napier


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)
}
like image 37
WTEDST Avatar answered Oct 12 '22 16:10

WTEDST