Per Eriksson
Per Eriksson

Reputation: 534

compute a value to a let struct property in init

I have a swift struct named Product which takes a Dictionary in its init method. I want to compute a price value in a local Price struct within my Product. I want this value to be a let constant since it won't ever change, but swift won't allow me to do that without using var, saying that the let constant is not properly initialized.

How can I make my value property inside my Price struct a let constant in this case?

struct Product {
    let price: Price

    init(dictionary: Dictionary<String, AnyObject>) {
        if let tmp = dictionary["price"] as? Dictionary<String, AnyObject> { price = Price(dictionary: tmp) } else { price = Price() }
    }

    struct Price {
        var value = ""

        init() {
        }

        init(dictionary: Dictionary<String, AnyObject>) {
            if let xForY = dictionary["xForY"] as? Array<Int> {
                if xForY.count == 2 {
                    value = "\(xForY[0]) for \(xForY[1])"
                }
            }
            if let xForPrice = dictionary["xForPrice"] as? Array<Int> {
                if value == "" && xForPrice.count == 2 {
                    value = "\(xForPrice[0]) / \(xForPrice[1]):-"
                }
            }
            if let reduced = dictionary["reduced"] as? String {
                if value == "" {
                    value = "\(reduced):-"
                }
            }
        }
    }
}

Upvotes: 0

Views: 995

Answers (2)

iOSX
iOSX

Reputation: 1300

You have to rewrite the code so that the compiler gets what you intend to do actually. It is not clever enough to deduce it from the way you coded it.

I would also suggest that you make the initializer for the Price struct failable instead of using an empty string for the value property. As a consequence of that change the price property of the Product struct becomes an optional.

struct Product {
    let price: Price?

    init(dictionary: Dictionary<String, AnyObject>) {
        if let tmp = dictionary["price"] as? Dictionary<String, AnyObject> {
            price = Price(dictionary: tmp)
        }
        else {
            price = nil
        }
    }

    struct Price {
        let value : String

        init?(dictionary: Dictionary<String, AnyObject>) {
            if let xForY = dictionary["xForY"] as? Array<Int> where xForY.count == 2 {
                value = "\(xForY[0]) for \(xForY[1])"
            }
            else if let xForPrice = dictionary["xForPrice"] as? Array<Int> where xForPrice.count == 2 {
                value = "\(xForPrice[0]) / \(xForPrice[1]):-"
            }
            else if let reduced = dictionary["reduced"] as? String {
                value = "\(reduced):-"
            }
            else {
                return nil
            }
        }
    }
}

Upvotes: 2

Dan Nichols
Dan Nichols

Reputation: 469

The trouble is that (1) you're assigning to value in the declaration, (2) you're not assigning a value in init(), and (3) you're referencing and reassigning value in init([String: AnyObject]). You can only assign a value to a constant once and can only reference its value after its been assigned to.

To fix the issue, you can either make your property publicly readonly:

private(set) var value: String = ""

Or you can use a second variable inside your init:

struct Price {
    let value: String

    init() {
        self.value = ""
    }

    init(dictionary: Dictionary<String, AnyObject>) {
        var v: String = ""
        if let xForY = dictionary["xForY"] as? Array<Int> {
            if xForY.count == 2 {
                v = "\(xForY[0]) for \(xForY[1])"
            }
        }
        if let xForPrice = dictionary["xForPrice"] as? Array<Int> {
            if v == "" && xForPrice.count == 2 {
                v = "\(xForPrice[0]) / \(xForPrice[1]):-"
            }
        }
        if let reduced = dictionary["reduced"] as? String {
            if v == "" {
                v = "\(reduced):-"
            }
        }
        self.value = v
    }
}

Upvotes: 1

Related Questions