【问题标题】:UITableView deleteRows not updating IndexPaths causing crash index out of rangeUITableView deleteRows 未更新 IndexPaths 导致崩溃索引超出范围
【发布时间】:2020-12-29 01:22:15
【问题描述】:

在 API 调用成功时调用以下代码以从列表中删除项目

self?.myWishlistArry?.remove(at: indexPath.row)
self?.myWishListTableView.deleteRows(at: [indexPath], with: .right)

以下是删除按钮的关闭

        myWishlistCell.closureForRemoveBtn = {
        [weak self]
        (productId, storeid) in
        self?.callAlertViewForRemoved(productid: productId, storeId: storeid, indexPath: indexPath)
    }

以下是显示提醒用户确认的代码。

    func callAlertViewForRemoved(productid :String, storeId: String, indexPath: IndexPath) {
    
    
    let alertController = UIAlertController(title: AppLocalString.ITEM_NOT_AVAILABLE_TEXT.localized(), message: AppLocalString.MY_EXLUDE_TEXT.localized(), preferredStyle: .alert)
    
    let okAction = UIAlertAction(title: AppLocalString.ALERT_YES.localized(), style: UIAlertAction.Style.default) {
        UIAlertAction in
        if self.listBool == false {
            //self.listBool = true
            self.callRemoveWishlist(productid :productid, storeId: storeId, indexPath: indexPath)
        }
    }
    
    let cancelAction = UIAlertAction(title: AppLocalString.Cancel_ORDER.localized(), style: UIAlertAction.Style.cancel) {
        UIAlertAction in
        NSLog("Cancel Pressed")
    }
    
    // Add the actions
    alertController.addAction(okAction)
    alertController.addAction(cancelAction)
    
    self.present(alertController, animated: true, completion: nil)
    
    
}

以下是代码api删除

    func callRemoveWishlist(productid :String, storeId: String, indexPath: IndexPath)  {
    
    listBool = true
    addLoading(view: view, random: removeRandom)
    let addFriendsBaseUrl = AppStrings.baseUrl + AppStrings.addToWishlistAPI
    var paramDict = [String : Any]()
    
    paramDict = ["type" : "remove",
                 "productid" : productid,
                 "storeid" : "\(storeId)",
        "userid" : UserDefaults.standard.value(forKey: AppStrings.userid) ?? ""]
    
    
    let baseParams = Utility.appendBaseParams(toDict: paramDict as! [String : String])
    
    NetworkResponseManager.getDataFromUrl(url: addFriendsBaseUrl, parameters: baseParams as! [String : String] , completionHandler: {
        [weak self]
        (response, error) in
        self?.listBool = false
        if (error == nil) {
            
            if let responseDict = response {
                
                let responseDict = AddToWishlistModel(JSON(responseDict))
                self?.removeLoading(view: self?.view, random: self?.removeRandom)
                if responseDict.status == 1
                {
                    self?.myWishlistArry?.remove(at: indexPath.row)
                    self?.myWishListTableView.deleteRows(at: [indexPath], with: .right)
                } else {
                    self?.showToast(message: AppLocalString.OOPS_TEXT.localized())
                }
            }
        } else {
             self?.showToast(message: AppLocalString.OOPS_TEXT.localized())
        }
    })
}

其他表格视图代码

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    
    return self.myWishlistArry?.count ?? 0
}


func numberOfSections(in tableView: UITableView) -> Int {
    return 1
}

现在这段代码第一次工作,但如果尝试删除另一个说索引超出范围的项目,则会导致崩溃。考虑列表 T1、T2、T3 和 T4 中是否有四个项目 第一次如果 我删除 T2 项目 indexPath.row 值为 1 现在项目和行被删除 如果我删除另一个项目说 T4 indexPath.row 的值来结果是 3 而不是 2 为什么会发生这种情况 为什么 indexpaths 没有更新?

【问题讨论】:

  • 这段代码怎么称呼?
  • 在 api 调用成功时尝试使用 DispatchQueue.main.async 调用仍然崩溃
  • 代码本身不会导致崩溃,除非它在捕获索引路径的闭包中执行。请添加上下文代码。
  • 是的,通过单击按钮从关闭中调用
  • @cora 重新加载整个表格视图效率低下,并且您摆脱了动画。

标签: ios swift uitableview tableview


【解决方案1】:

问题是索引路径被捕获,并且在单元格的顺序更改后没有被更新。

解决办法:

在单元格中声明闭包也传递单元格

var closureForRemoveBtn : ((UITableViewCell, String, String) -> Void)?

然后调用它

closureForRemoveBtn?(self, productId, storeId)

cellForRow中获取实际单元格的索引路径

myWishlistCell.closureForRemoveBtn = {
    [weak self]
    (actualCell, productId, storeid) in
    let actualIndexPath = tableView.indexPath(for: actualCell)!
    self?.callAlertViewForRemoved(productid: productId, storeId: storeid, indexPath: actualIndexPath)
}

或者更简单

var closureForRemoveBtn : ((UITableViewCell) -> Void)?

///

closureForRemoveBtn?(self)

///

myWishlistCell.closureForRemoveBtn = {
    [weak self] actualCell in
    let actualIndexPath = tableView.indexPath(for: actualCell)!
    self?.callAlertViewForRemoved(productid: actualCell.productId, storeId: actualCell.storeid, indexPath: actualIndexPath)
}

【讨论】:

    【解决方案2】:

    根据整个代码,看起来问题出在clojure

    如果您在 cellForRowAt 中的 clojure 中调用它,则索引路径是不同的(设置为在调用 cellForRowAt 时正确的值)。您应该根据愿望清单项目的 id 进行删除(删除项目时不会改变的东西)。

    例如创建一个类似的方法:

    func deleteWish(productId: string) {
        for i in myWishlistArry ?? [] {
            let product = myWishlistArry[i]
            if let product.productId == productId {
                 myWishlistArry?.remove(at: i)
                 myWishListTableView.deleteRows(at: [IndexPath(row: i, 0)], with: .right)
            }
        }
    
    }
    

    并调用 clojure deleteWish(productId: idOfDeletedProduct)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-06-20
      • 1970-01-01
      • 2021-12-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多