'String' does not convert to 'DictionaryIndex <String, [(String)]?>' Compiler error with very simple dictionary usage

I am trying to do very simple conversion dictionary strings to string arrays in Swift. The code looks like this:

class FirstViewController: UIViewController {

    var characters:[String] = []
    var adjacency = [String : [String]?]()

    override func viewDidLoad() {
        super.viewDidLoad()

        characters = loadCharacters()
        adjacency = loadAdjacency()

        var character:String = characters[0]
        var adj:[String] = adjacency[character] // This line gives the first compiler error
        adj = adjacency["a"] // This line gives the second compiler error

        println(adj)
    }

    func loadCharacters() -> [String] {
        return ["a", "b", "c"]
    }

    func loadAdjacency() -> [String : [String]?] {
        return ["a": ["a", "b", "c"], "b": ["b", "c", "d"], "c": ["c", "d", "e"]]
    }
}

      

First compiler error:   'String' is not convertible to 'DictionaryIndex<String, [(String)]?>'

Second compiler error:   '(String, [(String)]?)' is not convertible to '[String]'

As far as I can tell, both of these strings should be equivalent and correct - I am collecting an array of strings from a dictionary search using the string as the key. Where am I going wrong?

If I write it like this, the code compiles and runs correctly:

class SecondViewController: UIViewController {

    var keyArray:[String] = []
    var dict = [String : [String]?]()

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        keyArray = ["a", "b", "c"]
        dict = ["a": ["a", "b", "c"], "b": ["b", "c", "d"], "c": ["c", "d", "e"]]

        println(dict[keyArray[1]])

    }

}

      

By the way, I am using Xcode Version 6.1 (6A1052d) and I am running OSX 10.9.4. I'm going to switch to Yosemite in case something strange happens to my setup, but I think I was just missing something obvious here.

+3


source to share


2 answers


The error message here is not very helpful, it has nothing to do with the real problem at all ....

Solution 1:

var adj/*:[String]??*/ = adjacency[character] // adj is Optional<Optional<[String]>>
adj = adjacency["a"]
println(adj) // Optional(Optional(["a", "b", "c"]))

      

Solution 2:



var adj/*:[String]*/ = adjacency[character]!! // adj is [String]
adj = adjacency["a"]!!
println(adj) // [a, b, c]

      

Solution 3 is a safe way:

if let adj = adjacency[character] { // adj is Optional<String[]>
    if let adj2 = adj {  // adj2 is String[]
        println(adj2)
    }
}

      

+5


source


Quick Programming Guide :

The Swifts dictionary type implements the subtype for a key value as an index that accepts and receives an optional type. [...] The dictionary type uses an additional substring type to simulate the fact that not every key will have a value and provide a way to remove the value for a key by assigning a nil value to that key.

For example, the following code, which uses the Type Inference , myString

which is optional, is nil

:

let myDict = ["A" : "Alabama", "D" : "Delaware", "M" : "Montana"]
let myString = myDict["Z"] //dictionary subscripts return optionals (here, it String?)

      

You can use the Quick Help for the selected item on myString

to check if it is really optional ( Option ⌥+ click or Control ⌃+ Command ⌘+ ?).



Back to your code:

var adj:[String] = adjacency[character]

      

The preceding line cannot compile as it adjacency[character]

returns optional (maybe nil

), but at the same time you want to adj

be optional [String]

, which can never be nil

.

To solve this problem, you can rewrite your code like this:

override func viewDidLoad() {
    super.viewDidLoad()

    characters = loadCharacters()
    adjacency = loadAdjacency()

    var character = characters[0] //Quick Helps shows that it a String
    var adj = adjacency[character] //Quick Helps shows that it a [(String)]??

    if let tempAdj = adj { //returns [(String)]?
        if let unwrappedAdj = tempAdj { //returns [(String)]
            println(unwrappedAdj)
        } else {
            println("adj is nil")
        }
    } else {
        println("adj is nil")
    }

}

      

+3


source







All Articles