ios – CRASH尝试删除并重新加载相同的索引路径

前端之家收集整理的这篇文章主要介绍了ios – CRASH尝试删除并重新加载相同的索引路径前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。

CollectionViewController.m line 439
__50-[CollectionViewController photoLibraryDidChange:]_block_invoke

致命异常:NSInternalInconsistencyException
尝试删除并重新加载相同的索引路径({length = 2,path = 0 – 26007})

  1. - (void)photoLibraryDidChange:(PHChange *)changeInstance
  2. {
  3. // Call might come on any background queue. Re-dispatch to the main queue to handle it.
  4. dispatch_async(dispatch_get_main_queue(),^{
  5.  
  6. // check if there are changes to the assets (insertions,deletions,updates)
  7. PHFetchResultChangeDetails *collectionChanges = [changeInstance changeDetailsForFetchResult:self.assetsFetchResults];
  8. if (collectionChanges) {
  9.  
  10. // get the new fetch result
  11. self.assetsFetchResults = [collectionChanges fetchResultAfterChanges];
  12.  
  13. UICollectionView *collectionView = self.collectionView;
  14.  
  15. if (![collectionChanges hasIncrementalChanges] || [collectionChanges hasMoves]) {
  16. // we need to reload all if the incremental diffs are not available
  17. [collectionView reloadData];
  18.  
  19. } else {
  20. // if we have incremental diffs,tell the collection view to animate insertions and deletions
  21. [collectionView performBatchUpdates:^{
  22. NSIndexSet *removedIndexes = [collectionChanges removedIndexes];
  23. if ([removedIndexes count]) {
  24. [collectionView deleteItemsAtIndexPaths:[removedIndexes aapl_indexPathsFromIndexesWithSection:0]];
  25. }
  26. NSIndexSet *insertedIndexes = [collectionChanges insertedIndexes];
  27. if ([insertedIndexes count]) {
  28. [collectionView insertItemsAtIndexPaths:[insertedIndexes aapl_indexPathsFromIndexesWithSection:0]];
  29. }
  30. NSIndexSet *changedIndexes = [collectionChanges changedIndexes];
  31. if ([changedIndexes count]) {
  32. [collectionView reloadItemsAtIndexPaths:[changedIndexes aapl_indexPathsFromIndexesWithSection:0]];
  33. }
  34. } completion:NULL];
  35. }
  36.  
  37. [self resetCachedAssets];
  38. }
  39. });
  40. }

来源:https://developer.apple.com/devcenter/download.action?path=/wwdc_2014/wwdc_2014_sample_code/exampleappusingphotosframework.zip

我无法复制这个问题.可能是什么问题呢?非常感谢!

解决方法

我今天能够再现这个.为此,您需要:

>打开正在监听更改的应用程序
>打开照片应用程序,将一组照片从iCloud共享相册保存到您的照片库
>转到照片应用程序,删除其中的一些照片
>再次转到iCloud共享相册,并再次保存您删除的一些照片.你会看到这种情况发生.

我发现一个更新的代码似乎在这里更好地处理更新行为:
https://developer.apple.com/library/ios/documentation/Photos/Reference/PHPhotoLibraryChangeObserver_Protocol/

但是它仍然不会处理这种情况,也不会在要删除的索引更大时(即由于未捕获的异常’NSInternalInconsistencyException’终止应用程序),原因是:尝试从第0部分删除第9项,其中只包含9个更新前的项目).我创建了这个代码更新版本,处理这个更好,迄今为止还没有为我崩溃.

  1. func photoLibraryDidChange(changeInfo: PHChange!) {
  2.  
  3. // Photos may call this method on a background queue;
  4. // switch to the main queue to update the UI.
  5. dispatch_async(dispatch_get_main_queue()) {
  6.  
  7.  
  8. // Check for changes to the list of assets (insertions,moves,or updates).
  9. if let collectionChanges = changeInfo.changeDetailsForFetchResult(self.assetsFetchResult) {
  10.  
  11. // Get the new fetch result for future change tracking.
  12. self.assetsFetchResult = collectionChanges.fetchResultAfterChanges
  13.  
  14. if collectionChanges.hasIncrementalChanges {
  15.  
  16. // Get the changes as lists of index paths for updating the UI.
  17. var removedPaths: [NSIndexPath]?
  18. var insertedPaths: [NSIndexPath]?
  19. var changedPaths: [NSIndexPath]?
  20. if let removed = collectionChanges.removedIndexes {
  21. removedPaths = self.indexPathsFromIndexSetWithSection(removed,section: 0)
  22. }
  23. if let inserted = collectionChanges.insertedIndexes {
  24. insertedPaths = self.indexPathsFromIndexSetWithSection(inserted,section: 0)
  25. }
  26. if let changed = collectionChanges.changedIndexes {
  27. changedPaths = self.indexPathsFromIndexSetWithSection(changed,section: 0)
  28. }
  29. var shouldReload = false
  30. if changedPaths != nil && removedPaths != nil{
  31. for changedPath in changedPaths!{
  32. if contains(removedPaths!,changedPath){
  33. shouldReload = true
  34. break
  35. }
  36. }
  37.  
  38. }
  39.  
  40. if removedPaths?.last?.item >= self.assetsFetchResult.count{
  41. shouldReload = true
  42. }
  43.  
  44. if shouldReload{
  45. self.collectionView.reloadData()
  46. }else{
  47. // Tell the collection view to animate insertions/deletions/moves
  48. // and to refresh any cells that have changed content.
  49. self.collectionView.performBatchUpdates(
  50. {
  51. if let theRemovedPaths = removedPaths {
  52. self.collectionView.deleteItemsAtIndexPaths(theRemovedPaths)
  53. }
  54. if let theInsertedPaths = insertedPaths {
  55. self.collectionView.insertItemsAtIndexPaths(theInsertedPaths)
  56. }
  57. if let theChangedPaths = changedPaths{
  58. self.collectionView.reloadItemsAtIndexPaths(theChangedPaths)
  59. }
  60. if (collectionChanges.hasMoves) {
  61. collectionChanges.enumerateMovesWithBlock() { fromIndex,toIndex in
  62. let fromIndexPath = NSIndexPath(forItem: fromIndex,inSection: 0)
  63. let toIndexPath = NSIndexPath(forItem: toIndex,inSection: 0)
  64. self.collectionView.moveItemAtIndexPath(fromIndexPath,toIndexPath: toIndexPath)
  65. }
  66. }
  67. },completion: nil)
  68.  
  69. }
  70.  
  71. } else {
  72. // Detailed change information is not available;
  73. // repopulate the UI from the current fetch result.
  74. self.collectionView.reloadData()
  75. }
  76. }
  77. }
  78. }
  79.  
  80. func indexPathsFromIndexSetWithSection(indexSet:NSIndexSet?,section:Int) -> [NSIndexPath]?{
  81. if indexSet == nil{
  82. return nil
  83. }
  84. var indexPaths:[NSIndexPath] = []
  85.  
  86. indexSet?.enumerateIndexesUsingBlock { (index,Bool) -> Void in
  87. indexPaths.append(NSIndexPath(forItem: index,inSection: section))
  88. }
  89. return indexPaths
  90.  
  91. }

Swift 3 / iOS 10版本:

  1. func photoLibraryDidChange(_ changeInstance: PHChange) {
  2. guard let collectionView = self.collectionView else {
  3. return
  4. }
  5.  
  6. // Photos may call this method on a background queue;
  7. // switch to the main queue to update the UI.
  8. DispatchQueue.main.async {
  9. guard let fetchResults = self.fetchResults else {
  10. collectionView.reloadData()
  11. return
  12. }
  13.  
  14. // Check for changes to the list of assets (insertions,or updates).
  15. if let collectionChanges = changeInstance.changeDetails(for: fetchResults) {
  16. // Get the new fetch result for future change tracking.
  17. self.fetchResults = collectionChanges.fetchResultAfterChanges
  18.  
  19. if collectionChanges.hasIncrementalChanges {
  20. // Get the changes as lists of index paths for updating the UI.
  21. var removedPaths: [IndexPath]?
  22. var insertedPaths: [IndexPath]?
  23. var changedPaths: [IndexPath]?
  24. if let removed = collectionChanges.removedIndexes {
  25. removedPaths = self.indexPaths(from: removed,section: 0)
  26. }
  27. if let inserted = collectionChanges.insertedIndexes {
  28. insertedPaths = self.indexPaths(from:inserted,section: 0)
  29. }
  30. if let changed = collectionChanges.changedIndexes {
  31. changedPaths = self.indexPaths(from: changed,section: 0)
  32. }
  33. var shouldReload = false
  34. if let removedPaths = removedPaths,let changedPaths = changedPaths {
  35. for changedPath in changedPaths {
  36. if removedPaths.contains(changedPath) {
  37. shouldReload = true
  38. break
  39. }
  40. }
  41. }
  42.  
  43. if let item = removedPaths?.last?.item {
  44. if item >= fetchResults.count {
  45. shouldReload = true
  46. }
  47. }
  48.  
  49. if shouldReload {
  50. collectionView.reloadData()
  51. } else {
  52. // Tell the collection view to animate insertions/deletions/moves
  53. // and to refresh any cells that have changed content.
  54. collectionView.performBatchUpdates({
  55. if let theRemovedPaths = removedPaths {
  56. collectionView.deleteItems(at: theRemovedPaths)
  57. }
  58. if let theInsertedPaths = insertedPaths {
  59. collectionView.insertItems(at: theInsertedPaths)
  60. }
  61. if let theChangedPaths = changedPaths {
  62. collectionView.reloadItems(at: theChangedPaths)
  63. }
  64.  
  65. collectionChanges.enumerateMoves { fromIndex,toIndex in
  66. collectionView.moveItem(at: IndexPath(item: fromIndex,section: 0),to: IndexPath(item: toIndex,section: 0))
  67. }
  68. })
  69. }
  70. } else {
  71. // Detailed change information is not available;
  72. // repopulate the UI from the current fetch result.
  73. collectionView.reloadData()
  74. }
  75. }
  76. }
  77. }
  78.  
  79. func indexPaths(from indexSet: IndexSet?,section: Int) -> [IndexPath]? {
  80. guard let set = indexSet else {
  81. return nil
  82. }
  83.  
  84. return set.map { (index) -> IndexPath in
  85. return IndexPath(item: index,section: section)
  86. }
  87. }

猜你在找的iOS相关文章