Невозможный индекс падения диапазона - PullRequest
1 голос
/ 14 июня 2019

В приложении, над которым я работаю, мне нужно взять один элемент массива, указав индекс элемента в массиве, например array[index]. Это простой UICollectionView, который заполняется элементами, которые я получаю из массива.

Чтобы защититься от исключения индекса вне диапазона, я делаю это:

guard index < array.count else { return }
return array[index]

Несмотря на то, что у меня есть эта защита, я получил исключение индекса вне диапазона в строке array[index] (но не всегда).

Я не знаю, как это может произойти.

Я даже добавил еще одну проверку:

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

Итак, я делаю это (это фактический фрагмент кода из приложения):

...
guard let section = chatSections[optional: indexPath.section] else {
    return nil
}
guard indexPath.item < section.itemViewModels.count else {
    return nil
}
return section.itemViewModels[optional: indexPath.item]

Это не всегда происходит, но иногда я получаю исключение Index вне диапазона.

Exception

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

Кто-нибудь знает, как это возможно? Кто-нибудь сталкивался с такой проблемой?

Ответы [ 2 ]

1 голос
/ 14 июня 2019

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

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

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

0 голосов
/ 14 июня 2019
  • Я полагаю, что у вас есть множественный доступ к массиву источника данных (несколько потоков пытаются получить доступ к добавлению / удалению из массива).
  • , чтобы преодолеть это, вы должны использовать что-то для обеспечения синхронизации при доступеваш массив, есть несколько подходов, используя семафор или DispatchGroup.

Я бы рекомендовал использовать семафор, так как массив рассматривается как общий ресурс, например:

    private let semaphore = DispatchSemaphore(value: 1)
    private var _array:[Item] = []
    var array:[Item] {
        get {
            semaphore.wait()
            let result = self._allMessages
            defer {
                semaphore.signal()
            } 
            return result
        }
        set {
            semaphore.wait()
            self. _array = newValue
            semaphore.signal()
        }
    }

и использовать переменную array для доступа к источнику данных массива, а не кличное _array.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...