Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift error when trying to access Dictionary: `Could not find member 'subscript'`

Tags:

swift

This won't compile: enter image description here I've tried a couple different things; different ways of declaring the Dictionary, changing its type to match the nested-ness of the data. I also tried explicitly saying my Any was a collection so it could be subscripted. No dice.

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
    }


}
like image 932
rsmoz Avatar asked Jun 09 '14 20:06

rsmoz


2 Answers

Let's take a look at

response["current_rates"][exchange][currency]

response is declared as Dictionary<String,Any>(), so after the first subscript you try to call another two subscripts on an object of type Any.

Solution 1. Change the type of response to be a nested dictionary. Note that I added the question marks because anytime you access a dictionary item you get back an optional.

var response = Dictionary<String,Dictionary<String,Dictionary<String, Float>>>()

func valueForCurrency(currency :String, exchange :String) -> Float? {
    return response["current_rates"]?[exchange]?[currency]
}

Solution 2. Cast each level to a Dictionary as you parse. Make sure to still check if optional values exist.

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
}
like image 113
Dash Avatar answered Sep 21 '22 12:09

Dash


You can get nested dictionary data by following these steps:

let imageData: NSDictionary = userInfo["picture"]?["data"]? as NSDictionary
let profilePic = imageData["url"] as? String
like image 29
Dilip Patidar Avatar answered Sep 18 '22 12:09

Dilip Patidar