Why did my PHFetchResultChangeDetails change Indexes when everything I did was inserted at the end?

I am writing an iOS8 application using the framework. I really love PHFetchResultChangeDetails. But I don’t understand something: when I save new photos in the camera frame using the following code, I return the inserts and changes. I expect only insertions.

To make it specific:

[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{ PHAssetChangeRequest* newPhotoChangeRequest = [PHAssetChangeRequest creationRequestForAssetFromImage:image]; PHAssetCollectionChangeRequest* albumChangeRequest = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:_album]; [albumChangeRequest addAssets:[NSArray arrayWithObject:newPhotoChangeRequest.placeholderForCreatedAsset]]; ... 

The operation is to insert 3 photos using the above code. Before: 5 photos on ipad. After: 8 photos on the ipad. The breakpoint in the PHFetResultChangeDetails handler shows:

 (lldb) po insertionIndexPaths <__NSArrayM 0x7913be10>( <NSIndexPath: 0x78e39020> {length = 2, path = 0 - 5}, <NSIndexPath: 0x78e3c910> {length = 2, path = 0 - 6}, <NSIndexPath: 0x78e39480> {length = 2, path = 0 - 7} ) 

-> GOOD: makes sense! these are the photos i just inserted (last 3 index paths).

 (lldb) po changeIndexPaths <__NSArrayM 0x78e3c420>( <NSIndexPath: 0x78e3c7e0> {length = 2, path = 0 - 2}, <NSIndexPath: 0x78e3c7a0> {length = 2, path = 0 - 3}, <NSIndexPath: 0x78e3c7b0> {length = 2, path = 0 - 4} ) 

-> DO NOT UNDERSTAND: why are they considered "changed"? These are existing photos on the camera ... I did nothing to them.

Thank you for your help.

UPDATE: it looks like this might have something to do with the choice. I forgot to mention that this happens when some cells are already selected. I see that when new elements are inserted at the end of the View collection, some selected cells are not randomly selected - I think those that have changeIndexPaths. Wow, that sucks - I don’t see how my code can do this! Any clues?

UPDATE2: so it seems that false changeIndexPaths are always 3 indexPath immediately before the insertion paths (which are always at the end). Why?

UPDATE3: I also see failures in the UICollectionView performBatchUpdates when the data source is correctly updated in advance if there are both inserts and reloads. For example, when a change looks like this:

 <PHFetchResultChangeDetails: 0x1742b91a0> before=<PHFetchResult: 0x1702b5d20> count=31, after=<PHFetchResult: 0x1702b5ea0> count=33, hasIncremental=1 deleted=(null), inserted=<NSMutableIndexSet: 0x17444aef0>[number of indexes: 2 (in 2 ranges), indexes: (30 32)], changed=<NSMutableIndexSet: 0x17444a9b0>[number of indexes: 4 (in 2 ranges), indexes: (27-29 31)], hasMoves=0 

... then my application crashes to execBatchUpdates with the exception:

 *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'attempt to delete item 31 from section 0 which only contains 31 items before the update' 

Here is the performBatchUpdates code that I copied directly from the Apple documentation (!), So I see no reason why changeIndexPaths contains index 31, given that count = 31 before insertions:

  [self.collectionView performBatchUpdates:^{ if( deletionIndexPaths.count ) [self.collectionView deleteItemsAtIndexPaths:deletionIndexPaths]; if( insertionIndexPaths.count ) [self.collectionView insertItemsAtIndexPaths:insertionIndexPaths]; if( changeIndexPaths.count ) [self.collectionView reloadItemsAtIndexPaths:changeIndexPaths]; if( moveBlock ) moveBlock(self.collectionView); } ... 
+8
ios objective-c ios8 photos
source share
1 answer

Re: Update 3

Despite what the sample code says, changeIndexes cannot be used in executeBatchUpdates like this.

Indexes PHFetchResultChangeDetails.changedIndexes refer to the original result of the selection after removing indexes in removeIndexes and after adding new indexes to insertIndexes.

However, the UITableView and UICollectionView APIs require that the reloadItems * methods, when called in a batch update, have indexes before any other changes.

To fix this call, reload and move entries outside of batch updates, for example:

  [self.collectionView performBatchUpdates:^{ if( deletionIndexPaths.count ) [self.collectionView deleteItemsAtIndexPaths:deletionIndexPaths]; if( insertionIndexPaths.count ) [self.collectionView insertItemsAtIndexPaths:insertionIndexPaths]; } ... ] if( changeIndexPaths.count ) [self.collectionView reloadItemsAtIndexPaths:changeIndexPaths]; if( moveBlock ) moveBlock(self.collectionView); 
+3
source share

All Articles