Search code examples
swiftindexingsubscript

Cannot subscript a value of type '[xxx]' with an index of type '(Int, () -> ())'


I have this issue, the error accessing the index of an array. The index should be an integer, but its not working. I have tried initially with a variable, but in this example I have changed it to integer, 0, just to show its no the variable that is the issue.

   let location = SNStore.Welland[index].locations[0] {
                    if location.timestamp > 0 {

                    }
                }

the error is:

 Cannot subscript a value of type '[LocationStore]' with an index of type '(Int, () -> ())'

So could someone explain why the array doesn't want an int for its index? Its weird and I don't understand.

I checked for the declaration of locations in the quick help and it correctly shows how locations was declared in the struct. (in the struct it has curly braces on the end to initialise it empty.)

var locations: [LocationStore]

Solution

  • Subscripting in Swift is done behind the scenes by calling a special method subscript which takes an Int. So when you write:

    locations[0]
    

    Swift is really calling the subscript function with the value inside of []:

    locations.subscript(0)
    

    You can't call subscript directly, but it is there and you can define custom subscripting for your own classes by implementing subscript for them.

    You are confusing Swift with the extra curly braces { } which follow locations[0]. Swift interprets the { } and their contents as a closure with signature () -> () (takes no input, returns no output). Because of trailing closure syntax, Swift then interprets that closure as a second argument to the subscript function that is called on locations to perform the indexing. This subscripting function takes one argument, an Int, but you are passing two arguments, an Int and the () -> () closure. That is what the error message is telling you.

    The fix is to remove the extra { }:

    let location = SNStore.Welland[index].locations[0]
    if location.timestamp > 0 {
        // do something
    }