2015-09-15 3 views
0

У меня есть быстрая структура с именем Product, которая берет словарь в методе init. Я хочу вычислить цену value в локальной структуре Price внутри моего продукта. Я хочу, чтобы это значение было константой let, так как оно никогда не изменится, но быстрый не позволит мне это сделать без использования var, заявив, что константа let неправильно инициализирована.вычислить значение свойства let struct в init

Как я могу сделать свой объект value внутри моей цены struct a let constant в этом случае?

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):-" 
       } 
      } 
     } 
    } 
} 

ответ

2

Вы должны переписать код, чтобы компилятор получил то, что вы намереваетесь сделать на самом деле. Это недостаточно умно, чтобы вывести его из того, как вы его закодировали.

Я также предлагаю вам инициализировать для структуры Price struct failable вместо использования пустой строки для свойства value. В результате этого изменения свойство price структуры Product становится необязательным.

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 
      } 
     } 
    } 
} 
+0

мне понравился '' 'where' '' в выражении if let. Вероятно, я избежу того, чтобы структура была необязательной, так как я знаю, какое значение она должна иметь как резерв, а это «». Так что я пропустил последний одинокий случай '' 'else''' в собственных попытках. Спасибо @iOSX –

1

Беда в том, что (1) вы присваивание value в объявлении, (2) вы не присваивание значения в init(), и (3) вы ссылки и переназначение value в init([String: AnyObject]) , Вы можете присваивать значение константе один раз и ссылаться только на ее значение после ее назначения.

Чтобы устранить эту проблему, вы можете сделать вашу собственность публично доступен только для чтения:

private(set) var value: String = "" 

Или вы можете использовать вторую переменную внутри вашей 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 
    } 
}