Как безопасно обрабатывать диапазон asyn c, который пользователь меняет между проверками? - PullRequest
0 голосов
/ 03 августа 2020

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

var gloablIndex : Int

, которая отслеживает индекс страницы, отображаемой в данный момент пользователю. Это значение изменяется в методе UIScrollView:

func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) 
{
     globalIndex = currentIndex
}

В другой функции я проверяю, будет ли индекс текущей страницы - 1 находиться в диапазоне моего массива данных, например:

func changeLabel(velocity: CGPoint) 
{
    if velocity.x.isLess(than: CGFloat(0)) { 
        if ((0...dataSource.count).contains(globalIndex - 1)) { //Check One 
            if dataSource[globalIndex - 1].foo ?? false { //CheckTwo
                //do something
            }
        }
    } 
}

Эта функция вызывается в методе UIScrollView:

func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) { changeLabel() }

Когда пользователь быстро смахивает влево несколько раз на первой странице (globalIndex = 0), это может вызвать Fatal error: Index out of range: file в строке, содержащей //check two. Я считаю, что это происходит из-за того, что значение globalIndex изменяется между //check one и //check two.

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

1 Ответ

2 голосов
/ 03 августа 2020

Если у вас возникли проблемы с изменением значения, зафиксируйте его на месте.

func changeLabel(velocity: CGPoint) {
    let index = globalIndex - 1
    let data = dataSource

    if velocity.x.isLess(than: 0.0) {
        if data.indices.contains(index) { //Check One
            if data[index].foo ?? false { //CheckTwo
                //do something
            }
        }
    }
}

Лучше передать свойства в changeLabel как параметры.

func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
    changeLabel(velocity: velocity, data: dataSource, index: globalIndex - 1)
}

func changeLabel(velocity: CGPoint, data: [MyData], index: Int) {
        if velocity.x.isLess(than: 0.0) {
        if data.indices.contains(index) { //Check One
            if data[index].foo ?? false { //CheckTwo
                //do something
            }
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...