2014-12-04 62 views
8

我正在使用Photos框架编写iOS8应用程序。我真的很喜欢PHFetchResultChangeDetails。 但有些东西我不明白:当我使用下面的代码将新照片保存到相机胶卷时,我会返回插入和更改。我只希望插入。为什么我的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} 
) 

- > GOOD:有道理!这些是我刚刚插入的照片(最后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} 
) 

- >不明白:为什么这些被视为“改变”?这些是相机胶卷上的现有照片...我没有对他们做任何事情。

感谢您的帮助。

更新:它看起来可能与选择有关。我忽略了提及,这发生在已经选择了一些单元的情况下。我所看到的是,当在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的代码,这是我从苹果公司的文件复制直( !),所以我看不出为什么changeIndexPaths包含指数31,考虑到刀片前,数= 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

唉同样在这里。我插入了3个项目。我没有任何选择,但我应该插入,它是说:照片库更改 possen 2014-12-10 04:20:53

+0

我想出了我的问题,我调用fetchResultAfterChanges,两次进行相同的更改,一次在我的performChanges中,然后再次在回调块中。这导致PHFetchResults不显示我期望的差异并导致collectionView因不正确的更新而炸毁。再一次,我可能没有相同的情况,我的代码目前没有处理选择,但很快就会出现。 – possen 2014-12-22 06:24:16

回答

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); 
+0

谢谢!任何想法为什么会产生虚假的changeIndexPaths?现在我根本不使用changeIndexPaths,因为随机的似乎会生成 – xaphod 2015-06-10 19:28:18

相关问题