2015-06-03 52 views
0

我在PHChange事件發生後嘗試更改我的數據源時出現問題。我正在使用NSMutableOrderedSet作爲我的數據源類型。當PHChange發生時,它可以給你回三個可能的索引:removedIndexes,insertedIndexeschangedIndexesPhotos API將PHFetchResultChangeDetails索引轉換爲NSMutableOrderedSet

問題是我不知道如何才能在前面的數據源中反映這些更改。是否有人可以告訴我如何轉換PHChange中給出的索引以更新我的recentsCollectionDataSource。我的UICollectionView使用recentsCollectionDataSource作爲其數據源。

現在我想唯一的方法是手動枚舉和建立自己改變的索引,而不是使用PHFetchResultChangeDetails

我會很感激提供的任何幫助。任何關於使我的數據源的替代方法的建議也是受歡迎的。

代碼:

@property (nonatomic, strong) PHFetchResult *assetsFetchResult; 
@property (nonatomic, strong) NSMutableOrderedSet *recentsCollectionDataSource; 

- (void)setup 
{ 
    self.recentsCollectionDataSource = [[NSMutableOrderedSet alloc]init]; 

    self.assetsFetchResult = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum | PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAny options:nil]; 

    for (PHAssetCollection *sub in self.assetsFetchResult) 
    { 
     PHFetchResult *assetsInCollection = [PHAsset fetchAssetsInAssetCollection:sub options:nil]; 

     for (PHAsset *asset in assetsInCollection) 
     { 
      [self.recentsCollectionDataSource addObject:asset]; 
     } 
    } 

    if (self.recentsCollectionDataSource.count > 0) 
    { 
     NSArray *array = [self.recentsCollectionDataSource sortedArrayUsingDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:NO]]]; 

     self.recentsCollectionDataSource = [[NSMutableOrderedSet alloc]initWithArray:array]; 
    } 
} 

- (void)photoLibraryDidChange:(PHChange *)changeInstance 
{ 
    PHFetchResultChangeDetails *collectionChanges = [changeInstance changeDetailsForFetchResult:self.assetsFetchResult]; 

    if (collectionChanges) 
    { 
     dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0),^ 
     { 
      self.assetsFetchResult = [collectionChanges fetchResultAfterChanges]; 

      if (!collectionChanges.hasIncrementalChanges || collectionChanges.hasMoves) 
      { 
       dispatch_async(dispatch_get_main_queue(),^ 
       { 
        [self.recentsCollectionView reloadData]; 
       }); 
      } 
      else 
      { 
       dispatch_async(dispatch_get_main_queue(),^ 
       { 
        [self.recentsCollectionView performBatchUpdates:^ 
        { 
         NSIndexSet *removedIndexes = [collectionChanges removedIndexes]; 
         NSIndexSet *insertedIndexes = [collectionChanges insertedIndexes]; 
         NSIndexSet *changedIndexes = [collectionChanges changedIndexes]; 

         // Need to update our old recentsCollectionDataSource 
         // somehow, otherwise we get a crash. 

         if (removedIndexes.count) 
         { 
          [self.recentsCollectionView deleteItemsAtIndexPaths:[removedIndexes indexPathsFromIndexesWithSection:0]]; 
         } 

         if (insertedIndexes.count) 
         { 
          [self.recentsCollectionView insertItemsAtIndexPaths:[insertedIndexes indexPathsFromIndexesWithSection:0]]; 
         } 

         if (changedIndexes.count) 
         { 
          [self.recentsCollectionView reloadItemsAtIndexPaths:[changedIndexes indexPathsFromIndexesWithSection:0]]; 
         } 
        }completion:NULL]; 
       }); 
      } 
     }); 
    } 
} 

@implementation NSIndexSet (Convenience) 

- (NSArray *)indexPathsFromIndexesWithSection:(NSUInteger)section 
{ 
    NSMutableArray *indexPaths = [NSMutableArray arrayWithCapacity:self.count]; 

    [self enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) 
    { 
     [indexPaths addObject:[NSIndexPath indexPathForItem:idx inSection:section]]; 
    }]; 
    return indexPaths; 
} 

@end 

回答

0

我似乎解決這個問題(至少目前如此)。我分別建立了自己的刪除,插入和更改索引,這不像PHFetchResultChangeDetails那樣有效,但我不相信有另一種方法可以做到這一點。使用此代碼在iPhone 5上啃2600張照片需要大約4秒鐘的時間,所以不會太糟糕。

我發現了可能是與PHFetchResultChangeDetails一個錯誤,它並不投入的變化細節收藏的變化,所以你還不如表現良好,如果你想留在你的UI外觀的一致性整個集合再次獲取。

代碼:

- (void)photoLibraryDidChange:(PHChange *)changeInstance 
{ 
    PHFetchResultChangeDetails *collectionChanges = [changeInstance changeDetailsForFetchResult:self.assetsFetchResult]; 

    if (collectionChanges) 
    { 
     dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0),^ 
     { 
      self.assetsFetchResult = [collectionChanges fetchResultAfterChanges]; 

      NSMutableOrderedSet *newSet = [[NSMutableOrderedSet alloc]init]; 

      for (PHAssetCollection *sub in self.assetsFetchResult) 
      { 
       PHFetchResult *assetsInCollection = [PHAsset fetchAssetsInAssetCollection:sub options:nil]; 

       for (PHAsset *asset in assetsInCollection) 
       { 
        [newSet addObject:asset]; 
       } 
      } 

      NSMutableIndexSet *removedIndexes = [[NSMutableIndexSet alloc]init]; 
      NSMutableIndexSet *insertedIndexes = [[NSMutableIndexSet alloc]init]; 
      NSMutableIndexSet *changedIndexes = [[NSMutableIndexSet alloc]init]; 

      NSMutableArray *objectsToInsert = [[NSMutableArray alloc]init]; 

      if (newSet.count > 0) 
      { 
       NSArray *array = [newSet sortedArrayUsingDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:NO]]]; 

       newSet = [[NSMutableOrderedSet alloc]initWithArray:array]; 

       for (id obj in newSet) 
       { 
        NSUInteger idx = [self.recentsCollectionDataSource indexOfObject:obj]; 

        if (idx == NSNotFound) 
        { 
         [objectsToInsert addObject:obj]; 

         [insertedIndexes addIndex:[newSet indexOfObject:obj]]; 
        } 
        else 
        { 
         NSUInteger objIdx = [newSet indexOfObject:obj]; 

         PHAsset *oldAssetToCompare = (PHAsset *)[self.recentsCollectionDataSource objectAtIndex:idx]; 
         PHAsset *plausibleNewAssetToCompare = (PHAsset *)[newSet objectAtIndex:objIdx]; 

         if (![oldAssetToCompare isEqual:plausibleNewAssetToCompare]) 
         { 
          [changedIndexes addIndex:idx]; 
         } 
        } 
       } 

       for (id obj in self.recentsCollectionDataSource) 
       { 
        NSUInteger idx = [newSet indexOfObject:obj]; 

        if (idx == NSNotFound) 
        { 
         [removedIndexes addIndex:[self.recentsCollectionDataSource indexOfObject:obj]]; 
        } 
        else 
        { 
         NSUInteger objIdx = [self.recentsCollectionDataSource indexOfObject:obj]; 

         PHAsset *oldAssetToCompare = (PHAsset *)obj; 
         PHAsset *plausibleNewAssetToCompare = (PHAsset *)[newSet objectAtIndex:idx]; 

         if (![oldAssetToCompare isEqual:plausibleNewAssetToCompare]) 
         { 
          [changedIndexes addIndex:objIdx]; 
         } 
        } 
       } 
      } 

      if (removedIndexes.count > 0) 
      { 
       [self.recentsCollectionDataSource removeObjectsAtIndexes:removedIndexes]; 
      } 

      if (insertedIndexes.count > 0) 
      { 
       [self.recentsCollectionDataSource insertObjects:objectsToInsert atIndexes:insertedIndexes]; 
      } 

      if (!collectionChanges.hasIncrementalChanges || collectionChanges.hasMoves) 
      { 
       dispatch_async(dispatch_get_main_queue(),^ 
       { 
        [self.recentsCollectionView reloadData]; 
       }); 
      } 
      else 
      { 
       dispatch_async(dispatch_get_main_queue(),^ 
       { 
        [self.recentsCollectionView performBatchUpdates:^ 
        { 
         if (removedIndexes.count > 0) 
         { 
          [self.recentsCollectionView deleteItemsAtIndexPaths:[removedIndexes indexPathsFromIndexesWithSection:0]]; 
         } 

         if (insertedIndexes.count > 0) 
         { 
          [self.recentsCollectionView insertItemsAtIndexPaths:[insertedIndexes indexPathsFromIndexesWithSection:0]]; 
         } 

         if (changedIndexes.count > 0) 
         { 
          [self.recentsCollectionView reloadItemsAtIndexPaths:[changedIndexes indexPathsFromIndexesWithSection:0]]; 
         } 
        }completion:NULL]; 
       }); 
      } 
     }); 
    } 
}