Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reference `self` in Swift instance member declaration

Tags:

swift

I have a struct set up that accepts a reference as a single initialization parameter:

internal struct NodeState: Equatable {
    weak var node: Node! = nil
    // ...

    init(node: Node) {
        self.node = node
    }
}

I want to instantiate a NodeState as a member of the Node class, passing self in to set that weak reference:

public class Node: NSObject {
    internal var state = NodeState(node: self)
    // ...
}

…but I am getting this weird compile error:

Cannot convert value of type 'NSObject -> () -> Node' to expected argument type 'Node'

Am I not allowed to reference self in a member declaration in Swift?

like image 297
devios1 Avatar asked Apr 26 '16 21:04

devios1


3 Answers

In general you can't reference self in a member class declaration but you can if you make the property lazy and initialize it with a closure. Changing your Node class to something like this should work:

public class Node: NSObject {
    internal lazy var staticState: NodeState = { NodeState(node: self) }()
}

It works because the lazy property isn't initialized until after self is initialized. self has to be fully initialized before it can be used.

like image 110
Aaron Rasmussen Avatar answered Nov 10 '22 17:11

Aaron Rasmussen


Am I not allowed to reference self in a member declaration in Swift?

Sort of. You can't reference self (e.g. calling methods, passing self as a parameter) until the object is fully initialized.

You could use a lazy var in this case, which would work since it can't be accessed until the object is initialized. Here's an example:

public class Node: NSObject {
    internal lazy var staticState: NodeState = {
        return NodeState(node: self)
    }()
}
like image 22
Ben Kane Avatar answered Nov 10 '22 17:11

Ben Kane


Reference self in a closure?

public class Node: NSObject {

    lazy var staticState: () -> (NodeState) = {
        [unowned self] in
        return NodeState(node: self)

    }
}

I'm explicitly decorating self as unowned in the closure to prevent a retain cycle.

like image 1
JAL Avatar answered Nov 10 '22 16:11

JAL