简体   繁体   中英

Swift Lazy Property Initialization Circular Reference Compilation Error?

Can anyone explain why the following code will result in a circular reference error while compiling?

class Foo {
    
    let closure: ()->()
    
    func someFunc() {}
    
    init(closure: @escaping ()->()) {
        self.closure = closure
    }
}

class Bar {
    
    lazy var foo = Foo { [weak self] in // Circular Reference error here!
        self?.foo.someFunc()
    }
}

However if I change it to:

class Bar {

    lazy var foo: Foo = {
        return Foo { [weak self] in
            self?.foo.someFunc()
        }
    }()
}

then there is no circular reference error anymore.

I'm confused why one would cause an error, and the other would not.

The issue is here:

lazy var foo = Foo { [weak self] in
    self.foo.someFunc()
} //     ^^^

So you are defining foo in terms of foo . That's a circle. It's no different from saying

lazy var foo = self.foo

which is very obviously circular.

When you wrap the whole thing in a level of evaluation (the {...}() construct), the inner reference to self.foo is guaranteed not to be evaluated until later.

Updated:

The circular reference is in the type inferencing: It's the fact that foo 's type depends on self.foo 's type, which depends on foo 's type, which depends on self.foo 's type etc..

Previous Answer:

I think I figured out the root cause here (Thanks to some of my coworkers:):

My coworker noticed that this code compiles fine, which points out it might be a type inference issue. I was being thrown off by the wrapping closure, which apparently has nothing to do with the real issue.

class Bar {
    
    lazy var foo: Foo = Foo { [weak self] in
        self?.foo.someFunc()
    }
}

I think the in order for the compiler to evaluate Bar it must do type inference on the property foo , which requires the compiler to evaluate the property initialization code. However the property initialization code itself contains a reference to self / Bar , so in order for that code to be evaluated, Bar must be evaluated first. And thus the circular reference.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM