Безопасен ли доступ по индексу (subscript) к массиву в Swift?

Ответ

Нет, стандартный доступ по индексу array[index] небезопасен. При попытке обратиться к индексу за пределами диапазона 0..<array.count приложение аварийно завершится с ошибкой Fatal error: Index out of range.

Безопасные альтернативы:

  1. Явная проверка границ:

    if index >= 0 && index < array.count {
        let element = array[index]
    }
  2. Использование свойства indices:

    if array.indices.contains(index) {
        let element = array[index]
    }
  3. Создание безопасного сабскрипта через расширение (наиболее удобный способ):

    extension Array {
        subscript(safe index: Index) -> Element? {
            return indices.contains(index) ? self[index] : nil
        }
    }
    
    // Использование
    let item = array[safe: 5] // Возвращает Element? (nil при невалидном индексе)
  4. Использование высокоуровневых методов: Для многих задач вместо прямого доступа по индексу лучше подходят методы first, last, first(where:), dropFirst(_:) и т.д.

Почему нет встроенной безопасности? Это компромисс между безопасностью и производительностью. Явные проверки делают код надежнее и предотвращают случайные краши.

Ответ 18+ 🔞

А, ну это классика, блядь! Ты прям как тот Герасим, сука, лезешь в массив пальцем, не глядя, а там — пиздец, индекс за пределами! И приложение твоё — хлоп! — как Муму в мешке, на дно, ага.

Смотри, чувак, стандартный доступ array[index] — это как прыгнуть с крыши, не проверив, есть ли там сугроб. Может, повезёт, а может, и ебнешься об асфальт с ошибкой Fatal error: Index out of range. И всё, приехали, блядь. Совесть потом, как у Герасима, загложет: «Что ж я, мудак, сделал?»

Так что, ёпта, есть варианты поумнее, чтобы не быть таким максималистом, а то сразу мочить приложение.

Вариант первый — проверка, как взрослый.
Просто, как паспорт на входе проверить:

if index >= 0 && index < array.count {
    let element = array[index] // Всё чики-пуки
}

Но это, блядь, скучно, как Тургенев без мата.

Вариант второй — через indices.
Типа спросить у массива: «А у тебя вообще такой индекс в наличии?»

if array.indices.contains(index) {
    let element = array[index] // Да, есть, бери
}

Уже лучше, но всё равно рутина, блядь.

Вариант третий — расширение, чтоб вообще не париться.
Это как сделать себе волшебную палочку, которая не стреляет в глаз:

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

// Использование — красота, блядь!
let item = array[safe: 5] // Если индекс левый — вернёт nil, а не краш

Вот это уже, сука, удобно! Не надо метаться, как Герасим с мешком.

Вариант четвёртый — высокоуровневые методы.
А вообще, часто и не нужен этот индекс, блядь. Можно через first, last, first(where:) — они сами разберутся, не выебывайся.

А почему, спрашиваешь, встроенной безопасности нет?
А потому что, ёпта, производительность! Swift — не бабушка в подъезде, чтобы за тебя всё проверять. Хочешь скорость — будь добр, сам головой думай, а не тыкай пальцем в небо, как пиздёныш. Ядро — чистый изумруд, а не я дрочистый, понимаешь?

Короче, выбирай: либо проверяй вручную, либо делай сабскрипт safe, либо используй методы повыше. А лезть напрямую — это, блядь, игра в русскую рулетку с полным барабаном.