ios - 从 UICollectionViewController 中删除单元格的问题

标签 ios swift

我正在使用 UICollectionViewController,我正在尝试在所选项目的循环中使用 deleteItems,如下所示:

for item in (collectionView?.indexPathsForSelectedItems)!
        {

            let cell = self.collectionView?.cellForItem(at: item) as! ImageCollectionCell

            deleteLandGradingImage(images: ImagesData(jobNo: self.jobNo, ImageBytes: (self.array[item.item]["imageBytes"] as! String), Username: appDelegate.username)) { result in

                cell.imageView.layer.borderWidth = 0
                self.navigationItem.rightBarButtonItems = [self.editButton]
                self.editButton.isEnabled = true
                self.editButton.title = "Edit"
                self.doneButton.title = "Done"

                self.array.remove(at: item.item)
                self.collectionView?.deselectItem(at: item, animated: true)
                self.collectionView?.deleteItems(at: [item])

            }

        }


deleteLandGradingImage(images: ImagesData(jobNo: self.jobNo, ImageBytes: (self.array[item.item]["imageBytes"] as! String), Username: appDelegate.username)) { result in
}

是对删除单元格内图像并将其从数据库中删除的 API 的调用。

func deleteLandGradingImage(images: ImagesData, completionHandler:@escaping (_ result:Bool) -> Void) {

        //Define array for returning data

        var returnedResults = Bool()

        //Call API

        WebService().deleteLandGradingImages(images: images)
        {
            (result: Bool) in

            DispatchQueue.main.async {

                //Return our results

                returnedResults = result
                completionHandler(returnedResults)

            }

        }

    }

这是WebService中的方法:

func deleteLandGradingImages(images: ImagesData, completion: @escaping (_ result: Bool) -> Void)
    {

        var jsonDict = [AnyHashable: Any]()

        //Set Lot

        jsonDict["jobNo"] = images.jobNo

        //Set Image

        jsonDict["imageBytes"] = images.ImageBytes

        let jsonData: Data? = try? JSONSerialization.data(withJSONObject: jsonDict, options: .prettyPrinted)

        let urlComponents = NSURLComponents(string: webservice + "DeleteGradingImages");

        //Assign Username

        urlComponents?.user = appDelegate.username;

        //Assign Password

        urlComponents?.password = appDelegate.password;

        //Define our URL String

        let url = urlComponents?.url;

        //Define URL Request

        var request = URLRequest(url: url!)

        //Set Header Values for request

        request.setValue("application/json", forHTTPHeaderField: "Content-Type")

        //Set Header Values for request

        request.setValue("application/json", forHTTPHeaderField: "Accept")

        //Set Request Method to POST

        request.httpMethod = "POST"

        //Set Request Body to JSON Data

        request.httpBody = jsonData

        Alamofire.request(request)
            .responseJSON { response in

                if(response.error != nil)
                {
                    completion(false)
                }
                else
                {
                    let responseString = (String(data: response.data!, encoding: .utf8) != nil) as Bool
                    completion(responseString)
                }

        }
    }

我的循环问题是有时它有效,有时我会得到这个错误:

Invalid update: invalid number of items in section 0. The number of items contained in an existing section after the update (1) must be equal to the number of items contained in that section before the update (1), plus or minus the number of items inserted or deleted from that section (0 inserted, 1 deleted) and plus or minus the number of items moved into or out of that section (0 moved in, 0 moved out).

有时我会收到这个错误:

Thread 1: Fatal error: Index out of range

在这条线上

self.array.remove(at: item.item)

我做错了什么?

更新

我从一个答案中得到这个:

@IBAction func deleteButtonPressed(_ sender: Any) {

        let group = DispatchGroup()

        let indexPaths = (collectionView?.indexPathsForSelectedItems)!

        var deletes = Array<Dictionary<String, Any>>()

        for item in indexPaths {
            deletes.append(self.array[item.item])
        }

        for item in deletes {

            group.enter()

            deleteLandGradingImage(images: ImagesData(jobNo: self.jobNo, ImageBytes: (item["imageBytes"] as! String), Username: appDelegate.username)) { result in

                let i = self.array.index { (dic) -> Bool in

                    return true

                }
                if i != nil {
                    self.array.remove(at: i!)
                    group.leave()

                }

            }

        }

        group.notify(queue: .main) {
            for item in indexPaths {
                let cell = self.collectionView?.cellForItem(at: item) as! ImageCollectionCell
                cell.imageView.layer.borderWidth = 0
                self.collectionView?.deselectItem(at: item, animated: true)
            }
            self.navigationItem.rightBarButtonItems = [self.editButton]
            self.editButton.isEnabled = true
            self.editButton.title = "Edit"
            self.doneButton.title = "Done"
            self.collectionView?.deleteItems(at: indexPaths)

            if(self.array.count == 0)
            {
                self.imageCollectionDelegate?.ImageCollectionChange(false)
            }

        }

    }

但有时我会在这一行出错:

let cell = self.collectionView?.cellForItem(at: item) as! ImageCollectionCell

这是错误:

Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value

我注意到这只发生在 iPhone 上,如果我选择图像并滚动浏览 UICollectionView,然后单击删除按钮。

更新

我也试过这个:

@IBAction func deleteButtonPressed(_ sender: Any) {

        self.createIndicator()

        for item in (collectionView?.indexPathsForSelectedItems)! {

            if let cell = self.collectionView?.cellForItem(at: item) as! ImageCollectionCell? {
                deleteLandGradingImage(images: ImagesData(jobNo: self.jobNo, ImageBytes: (self.array[item.item]["imageBytes"] as! String), Username: appDelegate.username)) { result in

                    cell.imageView.layer.borderWidth = 0

                    self.collectionView?.performBatchUpdates({
                        self.array.remove(at: item.item)
                        self.collectionView?.deselectItem(at: item, animated: true)
                        self.collectionView?.deleteItems(at: [item])
                    }) { completed in
                        self.navigationItem.rightBarButtonItems = [self.editButton]
                        self.editButton.isEnabled = true
                        self.editButton.title = "Edit"
                        self.doneButton.title = "Done"
                        self.stopIndicator()

                    }
                }
            }
        }

    }

但是我得到这个错误:

Thread 1: Fatal error: Index out of range

在这一行:

self.array.remove(at: item.item)

最佳答案

有两个问题:

  1. 在使用 collectionView?.indexPathsForSelectedItems 的循环中更新 collectionView
  2. 过于频繁地调用 collectionView?.deleteItems(at: [item])

最好的选择是对所有索引执行网络请求,然后一步将它们从 collectionView 中移除。您可以使用 DispatchGroup 将请求合并到一个链中。

一些解释:删除两个项目。 1 和 2。有时 1 会先被删除,然后 indexPathsForSelectedItems 将只包含一个索引 (1)。但是循环将尝试删除 indexPath 2 处的项目。这是一个崩溃。

在您的代码中使用 DispatchGroup 的示例:

let group = DispatchGroup()
let indexPaths = (collectionView?.indexPathsForSelectedItems)!
var deletes = [<your type>]()
for item in indexPaths {
    deletes.append(array[item.item])
}
// TODO: Block UI with UIActivityIndicatorView
for item in deletes {
    group.enter()
    deleteLandGradingImage(images: ImagesData(jobNo: self.jobNo, ImageBytes: (item["imageBytes"] as! String), Username: appDelegate.username)) { result in
        let i = self.array.index(of: item)!
        self.array.remove(at: i)
        group.leave()
    }
}

group.notify(queue: .main) {
    self.navigationItem.rightBarButtonItems = [self.editButton]
    self.editButton.isEnabled = true
    self.editButton.title = "Edit"
    self.doneButton.title = "Done"
    self.collectionView?.deleteItems(at: indexPaths)
}

关于ios - 从 UICollectionViewController 中删除单元格的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50649619/

相关文章:

ios - 背景上的 SCNNode 大图像导致崩溃

ios - 在 GameViewController 中连接一个 UIButton 以在 SKScene (Swift) 中工作

ios - 如何在 Swift 中将 UnsafeMutablePointer<UInt8> 转换为 UIImage

ios - 无法获取用于在 iOS 中使用 GCM 实现推送通知的配置文件

swift - 如何使用 xcconfig 文件将环境配置添加到具有多个项目的工作区

swift - 泛型子类化

ios - 使用应用程序缓存时,为什么历史记录条目不会输入到 mobile safari 中?

ios - 在 Swift 中从 json 文件读回数据的正确方法是什么?

swift - 编辑核心数据列表项追加而不是添加

ios - 在 SwiftUI 中创建具有特定日期的 DatePicker