Быстрая ошибка при попытке доступа к Словарь: `Не удалось найти член 'subscript``
Это не скомпилируется:
Я пробовал пару разных вещей; различные способы объявления Словаря, изменение его типа для соответствия вложенности данных. Я также попытался явно сказать, что мой Any
был сборником, поэтому его можно было индексировать. Нет кубиков.
import UIKit
import Foundation
class CurrencyManager {
var response = Dictionary<String,Any>()
var symbols = []
struct Static {
static var token : dispatch_once_t = 0
static var instance : CurrencyManager?
}
class var shared: CurrencyManager {
dispatch_once(&Static.token) { Static.instance = CurrencyManager() }
return Static.instance!
}
init(){
assert(Static.instance == nil, "Singleton already initialized!")
getRates()
}
func defaultCurrency() -> String {
let countryCode = NSLocale.currentLocale().objectForKey(NSLocaleCountryCode) as String
let codesToCountries :Dictionary = [ "US":"USD" ]
if let localCurrency = codesToCountries[countryCode]{
return localCurrency
}
return "USD"
}
func updateBadgeCurrency() {
let chanCurr = defaultCurrency()
var currVal :Float = valueForCurrency(chanCurr, exchange: "Coinbase")!
UIApplication.sharedApplication().applicationIconBadgeNumber = Int(currVal)
}
func getRates() {
//Network code here
valueForCurrency("", exchange: "")
}
func valueForCurrency(currency :String, exchange :String) -> Float? {
return response["current_rates"][exchange][currency] as Float
}
}
Ответы
Ответ 1
Посмотрим на
response["current_rates"][exchange][currency]
response
объявляется как Dictionary<String,Any>()
, поэтому после первого индекса вы пытаетесь вызвать еще два индекса на объект типа Any.
Решение 1. Изменить тип ответа как вложенного словаря. Обратите внимание, что я добавил вопросительные знаки, потому что когда вы получаете доступ к элементу словаря, вы возвращаете необязательный.
var response = Dictionary<String,Dictionary<String,Dictionary<String, Float>>>()
func valueForCurrency(currency :String, exchange :String) -> Float? {
return response["current_rates"]?[exchange]?[currency]
}
Решение 2. Переведите каждый уровень в словарь при синтаксическом анализе. Обязательно проверяйте, существуют ли дополнительные значения.
var response = Dictionary<String,Any>()
func valueForCurrency(currency :String, exchange :String) -> Float? {
let exchanges = response["current_rates"] as? Dictionary<String,Any>
let currencies = exchanges?[exchange] as? Dictionary<String,Any>
return currencies?[currency] as? Float
}
Ответ 2
Вы можете получить вложенные словарные данные, выполнив следующие шаги:
let imageData: NSDictionary = userInfo["picture"]?["data"]? as NSDictionary
let profilePic = imageData["url"] as? String
Ответ 3
func valueForCurrency(currency :String, exchange :String) -> Float? {
if let exchanges = response["current_rates"] as? Dictionary<String,Any> {
if let currencies = exchanges[exchange] as? Dictionary<String,Any> {
return currencies[currency] as? Float
}
}
return nil
}
Ответ 4
response
объявляется как таковой:
var response = Dictionary<String,Any>()
Итак, компилятор думает, что response["current_rates"]
вернет Any
. Что может быть или не быть чем-то индексируемым индексом.
Вы должны уметь определять тип с вложенными словарями, тремя уровнями, и в итоге вы попадаете в float. Вам также необходимо развернуть дополнительную цепочку, поскольку словарь может иметь или не иметь значение для этого ключа, поэтому он расширяет доступ к индексу.
var response = Dictionary<String,Dictionary<String,Dictionary<String,Float>>>()
// ... populate dictionaries
println(response["current_rates"]?["a"]?["b"]) // The float