Search code examples
swiftfunctioncycleretain

swift retain cycle in function


I'd like to ask if retain cycle happens in this situation:

func someFunc() {
    var aVar = SomeObj()
    funcWithClosure(something, completionHandler: { _ -> Void in
        aVar = SomeObj() // new
    })
}

In this case, I refer back to aVar from the closure. I just wonder if this creates a retain cycle. If true, should I fix by:

func someFunc() {
    var aVar = SomeObj()
    funcWithClosure(something, completionHandler: { [weak aVar] _ -> Void in
        aVar = SomeObj() // new
    })
}

Solution

  • Just to expand on your question, you would get a retain cycle if aVar strongly references the closure. For example:

    func someFunc() {
        var aVar = SomeObj()
        aVar.funcWithClosure(something, completionHandler: {
            doSomethingWith(aVar)
        }
    }
    

    aVar strongly references the closure because it calls the function, and the closure strongly references aVar because it uses the variable in its body. To break the cycle, you could create a weak reference to aVar outside the closure, like this:

    func someFunc() {
        var aVar = SomeObj()
        weak var weakVar = aVar
        aVar.funcWithClosure(something, completionHandler: {
            if let weakVar = weakVar {
                 doSomethingWith(weakVar)
            }
        }
    }
    

    weakVar references aVar, so you use it in the place of aVar. And it references it weakly, so when aVar goes out of scope (when the function completes), its ref count can become zero. Inside the closure, since weakVar is a weak var, need to unwrap it somehow before using.

    In your question, you proposed adding [weak aVar] to the closure's capture list, which I don't believe would work.

    EDIT: fixed unwrapping weakVar as var, which is a keyword.