Быстрая ошибка при попытке доступа к Словарь: `Не удалось найти член 'subscript``

Это не скомпилируется: enter image description here Я пробовал пару разных вещей; различные способы объявления Словаря, изменение его типа для соответствия вложенности данных. Я также попытался явно сказать, что мой 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