приложение ios падает при удалении строки в uitableView - PullRequest
0 голосов
/ 01 октября 2018

У меня есть проблема в моем UITableView, который заполнен data: [(gamme: String, [(product: String, quantity: Double)])], все работает нормально: вставка строк и разделов, удаление строк и разделов, перезагрузка.Но иногда и когда я пытаюсь удалить много строк быстрым способом (построчно, проведя строкой таблицу и коснитесь (-)).это приводит к сбою, как на скриншоте.

Проблема трудно воспроизвести в приложении для разработки.но мои клиенты все еще сообщают об этом.Мои клиенты - профессионалы (не обычные пользователи), и ожидается, что они будут быстро использовать средние и большие данные.

enter image description here

, и это моефункция удаления строк:

    override func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {

    let delete = UITableViewRowAction(style: .destructive, title: "-") { (action, indexPath) in

        let cmd = self.groupedData[indexPath.section].1.remove(at: indexPath.row)
        tableView.deleteRows(at: [indexPath], with: .right)
        self.delegate?.didDeleteCmdLine(cmd)

        if self.groupedData[indexPath.section].1.count == 0 {
            self.groupedData.remove(at: indexPath.section)
            tableView.deleteSections(IndexSet(integer: indexPath.section), with: UITableViewRowAnimation.right)
        }
    }

    return [delete]
}

почему это происходит?

Это экран организатора xcode для сбоя

enter image description here Редактировать:

Проверка доступа к groupedData из любого потока, кроме основного, предложенного @Reinhard:

private var xgroupedData = [(gamme: GammePrdCnsPrcpl, [cmdline])]()

private var groupedData: [(gamme: GammePrdCnsPrcpl, [cmdline])] {
    get {
        if !Thread.isMainThread {
            fatalError("getting from not from main")
        }
        return xgroupedData
    }
    set {
        if !Thread.isMainThread {
            fatalError("setting from not from main")
        }
        xgroupedData = newValue
    }
}

, кроме groupedData переменная доступна только из основного потока

Ответы [ 7 ]

0 голосов
/ 23 октября 2018

Есть только обновление @ codeByThey's answer.Обновите ваш файл DataSource при удалении этой конкретной строки.

tableView.beginUpdates()
self.whatEverDataSource.remove(at: indexPath.row)
self.tableView.deleteRows(at: [indexPath], with: .automatic)
tableView.endUpdates()

Это приведет к тому, что ваш DataSource также обновится в то же время, что и TableView.Происходит сбой, возможно, из-за того, что DataSource не обновлен.

0 голосов
/ 24 октября 2018

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

func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]? {

    let delete = UITableViewRowAction(style: .destructive, title: "-") { [weak self] (action, indexPath) in

        // Use a weak reference to self to avoid any reference cycles.
        guard let weakSelf = self else {
            return
        }

        tableView.beginUpdates()

        let cmd: cmdline
        if weakSelf.groupedData[indexPath.section].1.count > 1 {
            cmd = weakSelf.groupedData[indexPath.section].1.remove(at: indexPath.row)
            tableView.deleteRows(at: [indexPath], with: .right)
        } else {
            // Remove the section when the `items` are empty or when the last item is to be removed.
            cmd = weakSelf.groupedData.remove(at: indexPath.section).1[indexPath.row]
            tableView.deleteSections([indexPath.section], with: .right)
        }
        weakSelf.delegate?.didDeleteCmdLine(cmd)

        tableView.endUpdates()
    }

    return [delete]
}
0 голосов
/ 21 октября 2018

После того, как пользователь нажал кнопку удаления, вы удаляете соответствующую строку и (если это была последняя строка этого раздела) соответствующий раздел из источника данных groupedData, который является массивом.Тем не менее, операции с массивами не являются потокобезопасными .
Может ли быть другой поток использует этот массив, когда он изменяется действием удаления?В этом случае приложение может аварийно завершить работу.Опасность, конечно, выше, когда несколько действий запускаются за короткое время, что, как вы и описали, выглядит так.
Один из способов (возможно, не самый лучший) избежать проблем с многопоточностью - это доступ к массиву только наосновной поток.
Если это замедляет основной поток, можно использовать синхронизированный массив, который допускает множественное чтение одновременно, но только одну запись, которая блокирует все чтения, см. здесь .

0 голосов
/ 17 октября 2018

вы можете попробовать это

         var myDataArray = ["one","two","three"]
         //wanna insert a row then in button action or any action write
         myDataArray.append("four")
         self.tblView.reloadData()
         // wanna delete a row
         myDataArray.removeObject("two")
         // you can remove data at any specific index liek
         //myDataArray.remove(at: 2)
         self.tblView.reloadData()
0 голосов
/ 01 октября 2018

Изменения в ответе Жоао Луиса Фернандеса .... попробуйте этот

func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
                if editingStyle == .delete {
                    objects.remove(at: indexPath.row)
                    tableView.deleteRows(at: [indexPath], with: .fade)
                } else if editingStyle == .insert {
                    // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view.
                }
            }

справочник (взлом с помощью swift. https://www.hackingwithswift.com/example-code/uikit/how-to-swipe-to-delete-uitableviewcells)

0 голосов
/ 01 октября 2018
tableView.beginUpdates()
self.tableView.deleteRows(at: [indexPath], with: .automatic)
tableView.endUpdates()
0 голосов
/ 01 октября 2018

попробуйте использовать эту функцию.

func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
    if editingStyle == .delete {
        print("Deleted")

        // do your delete your entires here..
        //

        self.tableView.deleteRows(at: [indexPath], with: .automatic)
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...