drekka
drekka

Reputation: 21883

Swift: Closure as a init argument in a class variable

I have some code that looks something like this:

class Calculator {
    private let estimateChanged:(newEstimate:Double) -> Void

    init(_ estimateChanged:(newEstimate:Double) -> Void) {
        self.estimateChanged = estimateChanged
    }
}

Which is used by another class. Currently I'm trying this to set a property containing a calculator:

class AnotherClass {
    private lazy var calculator = Calculator({ [unowned self] in
        self.loadEstimate()
    })
    func loadEstimate() {}
}

And I'm getting errors. Firstly where it says [unowned self] is giving me the error: 'unowned' cannot be applied to non-class type 'AnotherClass -> () -> AnotherClass'

Secondly on self.loadEstimate() I get: value of type 'AnotherClass -> () -> AnotherClass' has no member 'loadEstimate'

Everything I've read suggests to me that I've got this right, however I've not seen any example of setting a var with an instance of a class which takes a closure as an init argument.

Has anyone done this or knows what to try next? Or is there a better way to do this?

As a side note, the goal of this code was to effectively provide a way for the Calculator class to notify AnotherClass when a value has changed. I've looked around, but I'm not sure what techniques are best suited for doing this. Any suggestions?

Upvotes: 1

Views: 2382

Answers (1)

Adam Campbell
Adam Campbell

Reputation: 656

Here is as close as I could get to what you wanted by fiddling around in a playground. I had to change the types to match what you were passing to Calculator

class Calculator {
    private let estimateChanged:() -> Void

    init(_ estimateChanged:() -> Void) {
        self.estimateChanged = estimateChanged
    }
}

class AnotherClass {
    lazy var callback: () -> Void = { [unowned self] in
        self.loadEstimate()
    }
    var calculator: Calculator?

    // viewDidLoad in the case of a view controller
    init() {
        calculator = Calculator(callback)
    }

    func loadEstimate() {}
}

It is obviously not exactly what you wanted but it compiles. There seem to be issues when trying to refer to self in an un-initialized object (even when it seems you should be able to because you specify lazy and weak or unowned etc)

Upvotes: 2

Related Questions