[英]Why is UICollectionView reloadData crashing my app?
我正在使用uicollectionview显示一些照片,并且我有一个按钮,允许用户删除所选的照片。
除非我尝试删除用于填充uicollectionview的照片阵列中的最后一张照片,否则它会完美工作。 也就是说,如果有5张照片,那么如果用户删除了第5张照片而不是第1张,第2张,第3张或第4张照片,则会出现问题。 当我尝试删除第五张照片时,它在reloadData()上崩溃,并显示以下错误
由于未捕获的异常“ NSInternalInconsistencyException”而终止应用程序,原因:“试图从第0部分删除仅包含4个项目的第0部分中的项目4”
我不明白为什么会发生这种情况...错误甚至提到“试图删除”,但我从未真正告诉过我我正在删除任何内容。 我只是更改了源,然后要求它进行更新。 同样在错误消息中,它说该部分仅包含4个项目,而实际上是5张照片。 为什么?
有关我在做什么以及如何做的更多信息(使用Swift)...
我有一个ProgressPhotoSheetClass,从中实例化了对象progressPhotoSheet
这个progressPhotoSheet对象具有一组照片,这些照片可以具有优先级,例如照片ID,标题等
在我使用的部分中的项目数中
var numPics: Int = progressPhotoSheet.progressPhotos.count
return numPics
在我的cellForItemAtIndexPath中
let cell = collectionView.dequeueReusableCellWithReuseIdentifier(reuseIdentifier, forIndexPath: indexPath) as! PhotoHolder
cell.photoTitle.text = progressPhotoSheet.progressPhotos[indexPath.row].photoName
...等等..
删除我使用的项目时
progressPhotoSheet.deletePhoto(progressPhotoSheet.progressPhotos [indexPath.row] .photoId)
该操作会从设备和我的核心数据中删除照片,然后通过使用修改后的核心数据重新加载progressPhotoSheet.progressPhotos,因此它与以前完全一样,但是没有删除的照片。
然后我打电话
self.collectionView.reloadData()
哪个应该为新数据更新UICollectionView
我可以理解,如果我使用self.collectionView.deleteItemsAtIndexPaths(indexPaths),是否认为集合视图中的内容与数据源中的内容之间存在不匹配,因为这意味着忽略它们以使它们匹配我们需要删除一项-这有可能会出现不匹配的情况。。但是肯定使用self.collectionView.reloadData()并不重要,所做的更改仅应查看现在存在的数据并相应地更新UICollectionView。 ..
所以我的问题是...为什么我会收到此错误?我该怎么做才能解决问题,使我不明白呢?
编辑以包括更多信息
这是我的长焦代码
func deletePhoto(photoId: Int) {
// Set up Core Data Managed Object Context
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext!
// Fetch correct photo
let fetchRequest = NSFetchRequest(entityName: "CDProgressPhoto")
fetchRequest.predicate = NSPredicate(format: "photoId = %@", String(photoId))
// Save
if let fetchResults = managedContext.executeFetchRequest(fetchRequest, error: nil) as? [NSManagedObject] {
if fetchResults.count != 0{
// Will only be one photo with this photo id
var photo = fetchResults[0]
photo.setValue(true, forKey: "toDelete")
// Save the object
var error: NSError?
if !managedContext.save(&error) {
println("Could not save \(error), \(error?.userInfo)")
}
}
}
// Reload from core data
self.loadPhotoSheetFromCoreData()
}
self.loadPhotoSheetFromCoreData()然后在从核心数据中获取新数据之前清空EmptyPhotoSheet.progressPhotos。
private func loadPhotoSheetFromCoreData() {
if(self.hasPhotoSheet()) {
// Clear existing photos
self.progressPhotos = []
// Set up Core Data Managed Object Context
let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate
let managedContext = appDelegate.managedObjectContext!
let request = NSFetchRequest(entityName: "CDProgressPhoto")
let predicate1 = NSPredicate(format: "photoSheetId == %@", String(self.sheetId))
let predicate2 = NSPredicate(format: "toDelete == %@", false)
request.sortDescriptors = [NSSortDescriptor(key: "date", ascending: false) as NSSortDescriptor]
var predicatesArray: [NSPredicate] = [predicate1, predicate2]
//predicatesArray.append(predicate1)
request.predicate = NSCompoundPredicate.andPredicateWithSubpredicates(predicatesArray)
let existings = managedContext.executeFetchRequest(request, error: nil)
let existingPhotos: [CDProgressPhoto] = existings as! [CDProgressPhoto]
// for each photo make a ProgressPhoto object and add to progress photos array
for photo in existingPhotos {
var newPhoto: ProgressPhoto = ProgressPhoto()
newPhoto.photoSheetId = Int(photo.photoSheetId)
newPhoto.photoId = Int(photo.photoId)
newPhoto.photoName = photo.photoName
newPhoto.date = Int(photo.date)
newPhoto.url = photo.url
newPhoto.filename = photo.filename
newPhoto.height = Float(photo.height)
newPhoto.width = Float(photo.width)
newPhoto.selected = false
self.progressPhotos.append(newPhoto)
}
}
}
如您所见,此时照片尚未真正删除,我只是将toDelete标志设置为true,然后仅重新加载其中toDelete设置为false的项目。 这些照片稍后会根据网络连接等异步删除,因为它们也存储在服务器上以供主网站使用。
您是否尝试过在collectionView上调用invalidateLayout()? 如果您的视图为空,即存在0个元素,这可能会有所帮助。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.