Swift Array - проверка наличия индекса

В Swift существует ли способ проверить, существует ли индекс в массиве без генерирования фатальной ошибки?

Я надеялся, что смогу сделать что-то вроде этого:

let arr: [String] = ["foo", "bar"]
let str: String? = arr[1]
if let str2 = arr[2] as String? {
    // this wouldn't run
    println(str2)
} else {
    // this would be run
}

Но я получаю

фатальная ошибка: индекс массива вне диапазона

Ответ 1

Элегантный способ в Swift:

let isIndexValid = array.indices.contains(index)

Ответ 2

Просто проверьте, меньше ли индекс меньше размера массива:

if 2 < arr.count {
    ...
} else {
    ...
}

Ответ 3

Расширение Swift 3 и 4:

extension Collection {

    subscript(optional i: Index) -> Iterator.Element? {
        return self.indices.contains(i) ? self[i] : nil
    }

}

Используя это, вы возвращаете необязательное значение при добавлении ключевого слова, необязательного к вашему индексу, что означает, что ваша программа не сбой, даже если индекс выходит за пределы диапазона. В вашем примере:

let arr = ["foo", "bar"]
let str1 = arr[optional: 1] // --> str1 is now Optional("bar")
if let str2 = arr[optional: 2] {
    print(str2) // --> this still wouldn't run
} else {
    print("No string found at that index") // --> this would be printed
}

Ответ 4

Добавьте добавочный сахар:

extension Collection {
  subscript(safe index: Index) -> Iterator.Element? {
    guard indices.contains(index) else { return nil }
    return self[index]
  }
}

if let item = [a,b,c,d][safe:3] {print(item)}//Output: c

Повышает читаемость при выполнении стиля if let в сочетании с массивами

Ответ 5

Вы можете переписать это более безопасным способом проверки размера массива и использовать тернарный условный:

if let str2 = (arr.count > 2 ? arr[2] : nil) as String?