1 min read

Implicit retain cycle in lazy var

When writing Swift code, it's easy to to create retain cycles if you're not careful. It usually happens when a closure has a strong reference to self and self has a strong referenc to the the closure.

So just need to take note of all the self references in closure blocks, easy-peasy, right?. But today, I found a new kind of retain cycle I didn't noticed before.

class API {
    var status: String?
    
    var failureHandler: (() -> Void)?
    var completionHandler: (() -> Void)?
    
    init() {}
}

class ViewController: UIViewController {
    lazy var api: API = {
        let api = API()
        api.completionHandler = {
        }
        api.failureHandler = {
            // `api` reference Cause retian cycle
            // Use `self.api` instead of 'api' to fix it
            print(api.status ?? "")
        }
        
        return api
    }()
}

Here there is no self reference, but because api returned by the lazy closure is later referenced by self, a retain cycle is created.