Как уловить "Индекс вне диапазона" в Swift?

Мне бы очень хотелось использовать более простой классический блок catch try в моем коде Swift, но я не могу найти ничего, что бы это делало.

Мне просто нужно:

try {
// some code that causes a crash.
}
catch {
// okay well that crashed, so lets ignore this block and move on.
}  

Здесь моя дилемма, когда TableView перезагружается новыми данными, некоторая информация по-прежнему находится в ОЗУ, которая вызывает didEndDisplayingCell в tableView со свежим пустым источником данных для сбоя.

Поэтому я часто выставлял исключение Index out of range

Я пробовал это:

func tableView(tableView: UITableView, didEndDisplayingCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {

    do {
        let imageMessageBody = msgSections[indexPath.section].msg[indexPath.row] as? ImageMessageBody
        let cell = tableView.dequeueReusableCellWithIdentifier("ImageUploadCell", forIndexPath: indexPath) as! ImageCell
        cell.willEndDisplayingCell()
    } catch {
        print("Swift try catch is confusing...")
    }
}

Я также пробовал это:

func tableView(tableView: UITableView, didEndDisplayingCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
    print(indexPath.section)
    print(indexPath.row)

    if msgSections.count != 0 {
        if let msg = msgSections[indexPath.section].msg[indexPath.row] as? ImageMessageBody {
            let cell = tableView.dequeueReusableCellWithIdentifier("ImageUploadCell", forIndexPath: indexPath) as! ImageCell
            cell.willEndDisplayingCell()
        }
    }
}

Это очень низкоприоритетный блок кода, и я потратил много времени на пробную версию и ошибку, выяснив, какой обработчик ошибок встроен в быстрые работы для того, что кажется чрезвычайно уникальными ситуациями, когда у меня есть множество сценариев, как это тот, где код может сработать, и это не повлияет на пользовательский интерфейс.

Короче говоря, мне не нужно ничего интересного, но у Swift, похоже, есть чрезвычайно специфичные обработчики ошибок, которые различаются в зависимости от того, получаю ли я значение из возвращаемого значения функций или получаю значение из индекса массива, который может не существовать.

Есть ли простая попытка поймать Swift, как и любой другой популярный язык программирования?

Ответ 1

Как указано в комментариях и других ответах, лучше избегать подобных ситуаций. Однако в некоторых случаях вам может потребоваться проверить, существует ли элемент в массиве и безопасно ли он его вернуть. Для этого вы можете использовать расширение Array для безопасного возврата элемента массива.

Swift 3

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

Swift 2

extension Array {
    subscript (safe index: Int) -> Element? {
        return indices ~= index ? self[index] : nil
    }
}
  • Таким образом, вы никогда не нажимаете Index out of range
  • Вам нужно будет проверить, есть ли элемент nil

отсылайте этот вопрос для более


Попытка кода Swift3 на игровой площадке в Xcode 8.3.2 по-прежнему приводит к "crash", когда я даю ar = [1,3,4], тогда пусть v = ar [5]. Зачем? - Томас Темпельман 17 мая в 17:40

Вы должны использовать наш подстрочный индекс, а вместо let v = ar[5] он будет let v = ar[safe: 5].

По умолчанию получается значение из массива.

let boo = foo[index]

Добавьте использование настраиваемого индекса.

let boo = fee[safe: index]

// And we can warp the result using guard to keep the code going without throwing the exception.
guard let boo = foo[safe: index] else {
  return
}

Ответ 2

Swift Обработка ошибок (do/try/catch) не решение для исключений во время выполнения как "индекс вне диапазона".

Исключение во время выполнения (вы также можете увидеть, что это вызванная ловушка, фатальная ошибка, ошибка утверждения и т.д.) является признаком ошибки программиста. За исключением строчек -Ounchecked, Swift обычно гарантирует, что это приведет к сбою вашей программы, а не продолжению выполнения в состоянии bad/ undefined. Эти виды сбоев могут возникать в результате развертывания силы с помощью !, неявного развертывания, неправильного использования ссылок unowned, целых операций/преобразований, которые переполняются, fatalError() и precondition() и assert() s и т.д. (И, к сожалению, Objective-C исключения.)

Решение состоит в том, чтобы просто избежать этих ситуаций. В вашем случае проверьте границы массива:

if indexPath.section < msgSections.count && indexPath.row < msgSections[indexPath.section].msg.count {
    let msg = msgSections[indexPath.section].msg[indexPath.row]
    // ...
}

(Или, как говорит rmaddy в комментариях - исследуйте , почему эта проблема возникает! Это действительно не должно происходить вообще.)

Ответ 3

Вы можете попробовать другой подход к этому. Будет работать!

if msgSections != nil {
    for msg in msgSections[indexPath.section] {
        if msgSections[indexPath.section].index(of: msg) == indexPath.row {
            (Code)
        }
}