我正在使用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)
}
}
}
我对循环的问题是,有时候它有效,有时我会收到这个错误:
无效更新:第0部分中的项目数无效 更新(1)后现有部分中包含的项目必须是 等于该部分之前包含的项目数 更新(1),加上或减去插入或删除的项目数 该部分(0插入,1删除)和加号或减号的数量 移入或移出该部分的物品(0移入,0移出)。
有时我会收到此错误:
线程1:致命错误:索引超出范围
在这一行
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
这是错误:
线程1:致命错误:在展开时出乎意料地发现nil 可选值
我注意到这只发生在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()
}
}
}
}
}
但是我收到了这个错误:
线程1:致命错误:索引超出范围
在这一行:
self.array.remove(at: item.item)
答案 0 :(得分:3)
有两个问题:
collectionView?.indexPathsForSelectedItems
collectionView?.deleteItems(at: [item])
最佳选择是对所有索引执行网络请求,然后一步从collectionView中删除它们。您可以将一个链中的请求与DispatchGroup
组合在一起。
一些解释:删除两个项目。有时1将首先删除,之后indexPathsForSelectedItems
将只包含一个索引(1)。但是loop会尝试删除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)
}
答案 1 :(得分:0)
如果您收到错误
部分中的项目数无效
因为,在任何集合更改的情况下,它希望具有与其源数组相同数量的项目,您可以使用performBatchUpdates
解决此问题:
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
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"
}
}
}
}
答案 2 :(得分:0)
如上所述,您需要使用performBatchUpdates
方法进行UICollectionView更新。
来自文档:
您可以在想要制作多个的情况下使用此方法 在一个动画操作中更改为集合视图,如 反对几个单独的动画。您可以使用此方法 插入,删除,重新加载或移动单元格或使用它来更改单元格 与一个或多个单元格关联的布局参数。使用块 传递了updates参数以指定您的所有操作 想要表演。
这只是意味着您需要在performBatchUpdates
关闭内一次性删除所有项目。
您可以使用此代码执行此操作:
var indexes: [IndexPath] = []
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?.deselectItem(at: item, animated: true)
indexes.append(item.item)
}
}
}
indexes.forEach { self.array.remove(at: $0) }
collectionView?.performBatchUpdates({
self.collectionView?.deleteItems(at: [indexes])
}) { completed in
self.navigationItem.rightBarButtonItems = [self.editButton]
self.editButton.isEnabled = true
self.editButton.title = "Edit"
self.doneButton.title = "Done"
}
答案 3 :(得分:0)
我相信你应该首先从数组中删除项目而不是更新数据库我的项目有类似的问题,这个简单的更改解决了这个问题。我回家后尝试发布一些代码。希望这会有所帮助。