Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios UITableView deleteRows未更新索引路径导致崩溃索引超出范围_Ios_Swift_Uitableview_Tableview - Fatal编程技术网

Ios UITableView deleteRows未更新索引路径导致崩溃索引超出范围

Ios UITableView deleteRows未更新索引路径导致崩溃索引超出范围,ios,swift,uitableview,tableview,Ios,Swift,Uitableview,Tableview,在API调用成功从列表中删除项时调用以下代码 self?.myWishlistArry?.remove(at: indexPath.row) self?.myWishListTableView.deleteRows(at: [indexPath], with: .right) 下面是删除按钮的结束 myWishlistCell.closureForRemoveBtn = { [weak self] (productId, storeid) in

在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项indexath.row值是1,那么现在项和行都被删除了,如果我删除另一项,比如T4,indexath.row的值是3而不是2。为什么会发生这种情况?为什么indexPath没有更新?

基于整个代码,问题似乎是clojure

如果您在cellForRowAt中的clojure中调用它,则indexpath的值与调用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 deleteWishproductId:idOfDeletedProduct

根据整个代码,问题似乎出在clojure上

如果您在cellForRowAt中的clojure中调用它,则indexpath的值与调用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 deleteWishproductId:idOfDeletedProduct

问题在于索引路径被捕获,并且在单元格顺序更改后不会被更新

解决方案:

在单元格中,声明闭包以同时传递单元格

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

closureForRemoveBtn?(self, productId, storeId)
在cellForRow中,从实际单元格获取索引路径

或者更简单

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)
}

问题是索引路径被捕获,并且在单元格顺序更改后不会被更新

解决方案:

在单元格中,声明闭包以同时传递单元格

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

closureForRemoveBtn?(self, productId, storeId)
在cellForRow中,从实际单元格获取索引路径

或者更简单

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)
}

如何调用此代码?api调用成功后,尝试使用DispatchQueue.main.async调用,但仍会崩溃代码本身不会导致崩溃,除非它在捕获索引路径的闭包中执行。请添加上下文代码。单击button@cora重新加载整个表视图和删除动画的效率很低。如何调用此代码?api调用成功后,尝试使用DispatchQueue.main.async调用,但仍然会崩溃代码本身不会导致崩溃,除非它在闭包中执行在其中捕获索引路径。请添加上下文代码。单击button@cora重新加载整个表视图并删除动画的效率很低。