为什么我的PHFetchResultChangeDetails已经改变了索引,当我所做的只是插入到最后?

时间:2014-12-04 09:10:50

标签: ios objective-c ios8 photos

我正在使用Photos框架编写iOS8应用程序。我真的很喜欢PHFetchResultChangeDetails。 但有一些我不明白的事情:当我使用以下代码将新照片保存到相机胶卷时,我会回来插入和更改。我希望只插入。

使其具体化:

[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{

PHAssetChangeRequest* newPhotoChangeRequest = [PHAssetChangeRequest creationRequestForAssetFromImage:image];
PHAssetCollectionChangeRequest* albumChangeRequest = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:_album];
[albumChangeRequest addAssets:[NSArray arrayWithObject:newPhotoChangeRequest.placeholderForCreatedAsset]];
...

操作是使用上面的代码插入3张照片。之前:ipad上的5张照片。之后:ipad中的8张照片。 PHFetResultChangeDetails处理程序上的断点显示:

(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}
)

- &GT;好的:有道理!这些是我刚插入的照片(最后3个索引路径)。

(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}
)

- &GT;不要理解:为什么这些被认为是“改变了”?这些是相机胶卷上的现有照片......我没有对它们做任何事情。

感谢您的帮助。

更新:看起来它可能与选择有关。我忽略了提到,当已经选择了一些细胞时会发生这种情况。我所看到的是,当在collectionView的末尾插入新项目时,一些选定的单元格被随机取消选择 - 我认为那些具有changeIndexPaths。哇,太糟糕了 - 我看不出我的代码是如何做到的!任何提示?

UPDATE2:所以,看起来虚假的changeIndexPaths总是直接在插入路径之前的3个indexPaths(总是在结尾处)。为什么呢?!

UPDATE3:我还看到UICollectionView的performBatchUpdates崩溃,如果数据源事先是正确的,如果有插入和重新加载的话。例如,当更改看起来像这样:

<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

...然后我的应用程序在performBatchUpdates中崩溃,但有例外:

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

这是performBatchUpdates的代码,我直接从Apple文档(!)复制,因此我认为没有理由为changeIndexPaths包含索引31,因为在插入之前,count = 31:

 [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);
 } ...

1 个答案:

答案 0 :(得分:3)

回复:更新3

尽管示例代码说的是,changedIndexes不能像这样在performBatchUpdates中使用。

索引PHFetchResultChangeDetails.changedIndexes相对于删除removedIndexes中的索引之后的原始获取结果,并且添加了insertedIndexes中的新索引之后的

UITableView和UICollectionView API要求reloadItems *方法在批量更新中调用时,之前的索引任何其他更改。

要修复此调用,请在批量更新之外重新加载和移动条目,例如:

    [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);