0

I want to check if there is a value in a array and if so assign to a String using a if-left statement:

if let scoreValue = scoreValueArray[element!]{
               // do something with scoreValue 
            }

Error: Bound value in a conditional binding must be of optional type

So tried changing the ! to ? but error persists.

Any input appreciated.

scoreValueArray is an array of strings, where a String value is appended to array if a condition is met, then array is saved to NSUserdefaults.

So element is a int which corresponds to a index in the array, bt only if the index is occupied with a String, so

scoreValueArray[element!]

could return an 'Index out of bounds', hence want to use the if-let.

dancingbush
  • 2,131
  • 5
  • 30
  • 66
  • Can you provide some context on what exactly `scoreValueArray` is and what `element` is? – nhgrif Apr 02 '15 at 21:03
  • This means scoreValueArray[element!] doesn't return an optional value. You still need to check if your index is less than your array count – Leo Dabus Apr 02 '15 at 21:05

2 Answers2

3

Although the accepted answer clearly puts why optional binding is not available in the current implementation, it doesn't provide with a solution.

As it is shown in this answer, protocols provide an elegant way of safely checking the bounds of an array. Here's the Swift 2.0 version:

extension Array {
    subscript (safe index: Int) -> Element? {
        return indices ~= index ? self[index] : nil
    }
}

Which you can use like this:

let fruits = ["Apple", "Banana", "Cherry"]

if let fruit = fruits[safe: 4] {
   // Do something with the fruit
}
Community
  • 1
  • 1
pommefrite
  • 819
  • 10
  • 12
1

It's not clear what type your scoreValueArray is, but for the sake of this answer, I'm going to assume it's an array of Int.

var scoreValueArray: Array<Int>

Now, if we look the definition of the Array struct, we'll find this:

struct Array<T> : MutableCollectionType, Sliceable {
    // other stuff...

    subscript (index: Int) -> T

    // more stuff
}

So, calling the subscript method on our array (which is what we do when we say scoreValueArray) returns a non-optional. And non-optionals cannot be used in the conditional binding if let/if var statements.

We can duplicate this error message in a more simple example:

let foo: Int = 3

if let bar = foo {
    // same error
}

This produces the same error. If we instead do something more like the following, we can avoid the error:

let foo: Int? = 3

if let bar = foo {
    // perfectly valid
}

This is different from a dictionary, whose subscript method does return an optional (T?). A dictionary will return a value if the key passed in the subscript is found or nil if there is no value for the passed key.

We must avoid array-index-out-of-bounds exceptions in the same way we always do... by checking the array's length:

if element < scoreValueArray.count {
    scoreValue = scoreValueArray[element]
}
nhgrif
  • 61,578
  • 25
  • 134
  • 173