Прерывистый сбой: Попытка удалить строку 0 из раздела 0, который содержит только 0 строк перед обновлением - PullRequest
0 голосов
/ 28 февраля 2019

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

Я просматриваю несколько сообщений StackOverflow об этом сбое, но не могу получитьТочная причина этой аварии.

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

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

enter image description here

@available(iOS 11.0, *)
private func actionForType(alertID: String, swipeAction: AlertSwipeActionType, indexPath: IndexPath) -> UIContextualAction {
    let contexualAction = UIContextualAction(style: .normal, title: nil) { [weak self] (action, view, completion) in

        guard let strongSelf = self else {
            return
        }

        switch swipeAction {
        ......
        case .affirm:
            completion(true)
            strongSelf.dispositionAlert(id: alertID, status: true, indexPath: indexPath)
        ......
        }
    }

    ......
    return contexualAction
}

fileprivate func dispositionAlert(id: String, status: Bool, indexPath: IndexPath) {
    let dispositionRequest = AlertDispositionUpdateBody(id: id, disposition: status, questionId: nil)
    self.updateAlertDispositionStatus(request: dispositionRequest) { [weak self] in

        guard let strongSelf = self else {
            return
        }
        strongSelf.removeCellWithAnimationAt(indexPath: indexPath)
        strongSelf.loadAlerts()
    }
}

fileprivate func removeCellWithAnimationAt(indexPath: IndexPath) {
    DispatchQueue.main.async {
        self.tableView.beginUpdates() // likely not required
        self.removeAlertAtIndexPath(indexPath)
        self.tableView.deleteRows(at: [indexPath], with: .fade)
        self.tableView.endUpdates() // likely not required either
    }
}

@objc func loadAlerts() {
    self.startLoadingAnimation()
    self.alertsFooterList.removeAll()

    AlertsManager.sharedInstance.loadMemberAlerts()
}

fileprivate func removeAlertAtIndexPath(_ indexPath: IndexPath) {
    let alertStatus = self.alertTabType.statusToLoad[indexPath.section]
    if let alerts = self.alertsList[alertStatus], 
       alerts.count > indexPath.row {
       self.alertsList[alertStatus]?.remove(at: indexPath.row)
    }
}

Ответы [ 2 ]

0 голосов
/ 28 февраля 2019

Авария говорит вам, что произошло: когда вы пытаетесь удалить строку, она уже была удалена.Теперь это кажется странным, потому что строка была там, когда вы представляли alertView.Таким образом, между моментом представления alertView и удаления строки, строка была удалена каким-либо другим источником.Чтение вашего кода это явно возможно.Существует две задержки между представлением предупреждения и удалением строки.Первое, возможно, очень долгое время, пока пользователь не подтвердит удаление, а второе - DispatchQueue.main.async, которое, как правило, довольно быстрое, но все же может вызывать ошибки такого типа.

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

Более глубокая проблема заключается в том, что у вас есть два источника правды - таблица и ваш источник данных, и они не синхронизированы.Лучше сначала обновить источник данных, а затем иметь код, который автоматически синхронизирует представление таблицы.Таким образом, они всегда остаются в синхронизации.https://github.com/Instagram/IGListKit - это решение, которое уже реализует это, и вы можете получить значение, используя его.

0 голосов
/ 28 февраля 2019

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

код: swift

fileprivate func removeCellWithAnimationAt(indexPath: IndexPath) {
    DispatchQueue.main.async {
        self.removeAlertAtIndexPath(indexPath)
        self.tableView.numberOfRows(inSection: indexPath.section) // called first
        self.tableView.deleteRows(at: [indexPath], with: .fade)
    }
}

Надеюсь, этот код работает.

...