2

I am busy converting to Swift and am trying to figure out how to do the following in Swift

NSArray arrayOfStrings1 = {@"Substring1", @"Substring2", nil};

Dictionary dict = {@"MainString1", arrayOfStrings1};

So in Swift I have the following:

var dictionary = [String: Array<String>]()  // is this correct ??
var array: [String] = ["Substring1", "Substring2"]


dictionary["MainString1"] = ["Substring1.1", "Substring1.2"]
dictionary["MainString2"] = ["Substring2.1", "Substring2.2"]

Now in order to access the array I use

let array = dictionary["MainString1"]

let item0 = array[0]

but this fails with a compiler error which seems to indicate that array is in fact a String not an array of strings.

What am I missing here?

Duncan Groenewald
  • 8,496
  • 6
  • 41
  • 76

1 Answers1

3

The issue is actually that a subscript lookup for a Dictionary in Swift returns an optional value:

enter image description here

This is a pretty great feature - you can't be guaranteed that the key you're looking for necessarily corresponds to a value. So Swift makes sure you know that you might not get a value from your lookup.

This differs a little bit from subscript behavior for an Array, which will always return a value. This is a semantically-driven decision - it's common in languages for dictionary lookups to return null if there is no key - but if you try to access an array index that does not exist (because it's out of bounds), an exception will be thrown. This is how Swift guarantees you'll get a value back from an array subscript: Either you'll get one, or you'll have to catch an exception. Dictionaries are a little more lenient - they're "used to" not having the value you're asking for.

As a result, you can use optional binding to only use the item if it actually has a value, like so:

if let theArray = dictionary["MainString1"] {
    let item0 = theArray[0]
} else {
    NSLog("There was no value for key 'MainString1'")
}
Craig Otis
  • 31,257
  • 32
  • 136
  • 234
  • All nice with out-of-bounds array access **except** exceptions are not supported for recoverable errors. But Swift was supposed to prevent crashes and optionals was one way to do that! – zaph Oct 02 '14 at 22:39
  • @Zaph Are you saying that you'd prefer to see the subscript behavior for `Array` return an optional? (If so, I agree.) – Craig Otis Oct 03 '14 at 10:11
  • @CraigOtis Yes. Otherwise the item count of the array has to be checked prior to accessing and that is essentially the "old style" and may not be done. – zaph Oct 03 '14 at 11:17
  • 1
    @Zaph In that case, you might like my other question. :-) http://stackoverflow.com/questions/25329186/safe-bounds-checked-array-lookup-in-swift-through-optional-bindings – Craig Otis Oct 03 '14 at 11:41