123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802 |
- /*
-
- MIT License (MIT)
-
- Copyright (c) 2015 Clement CN Tsang
-
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
-
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- THE SOFTWARE.
-
- */
- #import "CTAssetsPickerDefines.h"
- #import "CTAssetsPickerController.h"
- #import "CTAssetsPickerController+Internal.h"
- #import "CTAssetsGridViewController.h"
- #import "CTAssetsGridView.h"
- #import "CTAssetsGridViewLayout.h"
- #import "CTAssetsGridViewCell.h"
- #import "CTAssetsGridViewFooter.h"
- #import "CTAssetsPickerNoAssetsView.h"
- #import "CTAssetsPageViewController.h"
- #import "CTAssetsPageViewController+Internal.h"
- #import "CTAssetsViewControllerTransition.h"
- #import "UICollectionView+CTAssetsPickerController.h"
- #import "NSIndexSet+CTAssetsPickerController.h"
- #import "NSBundle+CTAssetsPickerController.h"
- #import "PHImageManager+CTAssetsPickerController.h"
- NSString * const CTAssetsGridViewCellIdentifier = @"CTAssetsGridViewCellIdentifier";
- NSString * const CTAssetsGridViewFooterIdentifier = @"CTAssetsGridViewFooterIdentifier";
- @interface CTAssetsGridViewController ()
- <PHPhotoLibraryChangeObserver>
- @property (nonatomic, weak) CTAssetsPickerController *picker;
- @property (nonatomic, strong) PHFetchResult *fetchResult;
- @property (nonatomic, strong) PHCachingImageManager *imageManager;
- @property (nonatomic, assign) CGRect previousPreheatRect;
- @property (nonatomic, assign) CGRect previousBounds;
- @property (nonatomic, strong) CTAssetsGridViewFooter *footer;
- @property (nonatomic, strong) CTAssetsPickerNoAssetsView *noAssetsView;
- @property (nonatomic, assign) BOOL didLayoutSubviews;
- @end
- @implementation CTAssetsGridViewController
- - (instancetype)init
- {
- CTAssetsGridViewLayout *layout = [CTAssetsGridViewLayout new];
-
- if (self = [super initWithCollectionViewLayout:layout])
- {
- _imageManager = [PHCachingImageManager new];
-
- self.extendedLayoutIncludesOpaqueBars = YES;
-
- self.collectionView.allowsMultipleSelection = YES;
-
- [self.collectionView registerClass:CTAssetsGridViewCell.class
- forCellWithReuseIdentifier:CTAssetsGridViewCellIdentifier];
-
- [self.collectionView registerClass:CTAssetsGridViewFooter.class
- forSupplementaryViewOfKind:UICollectionElementKindSectionFooter
- withReuseIdentifier:CTAssetsGridViewFooterIdentifier];
-
- [self addNotificationObserver];
- }
-
- return self;
- }
- - (void)viewDidLoad
- {
- [super viewDidLoad];
- [self setupViews];
- [self registerChangeObserver];
- [self addGestureRecognizer];
- [self addNotificationObserver];
- [self resetCachedAssetImages];
- }
- - (void)viewWillAppear:(BOOL)animated
- {
- [super viewWillAppear:animated];
- [self setupButtons];
- [self setupAssets];
- [self updateTitle:self.picker.selectedAssets];
- [self updateButton:self.picker.selectedAssets];
- }
- - (void)viewDidAppear:(BOOL)animated
- {
- [super viewDidAppear:animated];
- [self updateCachedAssetImages];
- }
- - (void)viewWillLayoutSubviews
- {
- [super viewWillLayoutSubviews];
-
- if (!CGRectEqualToRect(self.view.bounds, self.previousBounds))
- {
- [self updateCollectionViewLayout];
- self.previousBounds = self.view.bounds;
- }
- }
- - (void)viewDidLayoutSubviews
- {
- [super viewDidLayoutSubviews];
-
- if (!self.didLayoutSubviews && self.fetchResult.count > 0)
- {
- [self scrollToBottomIfNeeded];
- self.didLayoutSubviews = YES;
- }
- }
- - (void)dealloc
- {
- [self unregisterChangeObserver];
- [self removeNotificationObserver];
- }
- #pragma mark - Accessors
- - (CTAssetsPickerController *)picker
- {
- return (CTAssetsPickerController *)self.splitViewController.parentViewController;
- }
- - (PHAsset *)assetAtIndexPath:(NSIndexPath *)indexPath
- {
- return (self.fetchResult.count > 0) ? self.fetchResult[indexPath.item] : nil;
- }
- #pragma mark - Setup
- - (void)setupViews
- {
- self.collectionView.backgroundColor = [UIColor colorWithWhite:0 alpha:0];
- CTAssetsGridView *gridView = [CTAssetsGridView new];
- [self.view insertSubview:gridView atIndex:0];
- [self.view setNeedsUpdateConstraints];
- }
- - (void)setupButtons
- {
- if (self.navigationItem.rightBarButtonItem == nil)
- {
- NSString *title = (self.picker.doneButtonTitle) ?
- self.picker.doneButtonTitle : CTAssetsPickerLocalizedString(@"Done", nil);
-
- self.navigationItem.rightBarButtonItem =
- [[UIBarButtonItem alloc] initWithTitle:title
- style:UIBarButtonItemStyleDone
- target:self.picker
- action:@selector(finishPickingAssets:)];
- }
- }
- - (void)setupAssets
- {
- PHFetchResult *fetchResult =
- [PHAsset fetchAssetsInAssetCollection:self.assetCollection
- options:self.picker.assetsFetchOptions];
-
- self.fetchResult = fetchResult;
- [self reloadData];
- }
- #pragma mark - Collection view layout
- - (void)updateCollectionViewLayout
- {
- UITraitCollection *trait = self.traitCollection;
- CGSize contentSize = self.view.bounds.size;
- UICollectionViewLayout *layout;
- NSArray *attributes = [self.collectionView.collectionViewLayout layoutAttributesForElementsInRect:self.collectionView.bounds];
- UICollectionViewLayoutAttributes *attr = (UICollectionViewLayoutAttributes*)attributes.firstObject;
- // new content size should be at least of first item size, else ignoring
- if (contentSize.width < attr.size.width || contentSize.height < attr.size.height) {
- return;
- }
- if ([self.picker.delegate respondsToSelector:@selector(assetsPickerController:collectionViewLayoutForContentSize:traitCollection:)]) {
- layout = [self.picker.delegate assetsPickerController:self.picker collectionViewLayoutForContentSize:contentSize traitCollection:trait];
- } else {
- layout = [[CTAssetsGridViewLayout alloc] initWithContentSize:contentSize traitCollection:trait];
- }
-
- __weak CTAssetsGridViewController *weakSelf = self;
-
- [self.collectionView setCollectionViewLayout:layout animated:NO completion:^(BOOL finished){
- [weakSelf.collectionView reloadItemsAtIndexPaths:[weakSelf.collectionView indexPathsForVisibleItems]];
- }];
- }
- #pragma mark - Scroll to bottom
- - (void)scrollToBottomIfNeeded
- {
- BOOL shouldScrollToBottom;
-
- if ([self.picker.delegate respondsToSelector:@selector(assetsPickerController:shouldScrollToBottomForAssetCollection:)])
- shouldScrollToBottom = [self.picker.delegate assetsPickerController:self.picker shouldScrollToBottomForAssetCollection:self.assetCollection];
- else
- shouldScrollToBottom = YES;
-
- if (shouldScrollToBottom)
- {
- NSIndexPath *indexPath = [NSIndexPath indexPathForItem:self.fetchResult.count-1 inSection:0];
- [self.collectionView scrollToItemAtIndexPath:indexPath atScrollPosition:UICollectionViewScrollPositionTop animated:NO];
- }
- }
- #pragma mark - Notifications
- - (void)addNotificationObserver
- {
- NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
-
- [center addObserver:self
- selector:@selector(assetsPickerSelectedAssetsDidChange:)
- name:CTAssetsPickerSelectedAssetsDidChangeNotification
- object:nil];
-
- [center addObserver:self
- selector:@selector(assetsPickerDidSelectAsset:)
- name:CTAssetsPickerDidSelectAssetNotification
- object:nil];
- [center addObserver:self
- selector:@selector(assetsPickerDidDeselectAsset:)
- name:CTAssetsPickerDidDeselectAssetNotification
- object:nil];
- }
- - (void)removeNotificationObserver
- {
- NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
-
- [center removeObserver:self name:CTAssetsPickerSelectedAssetsDidChangeNotification object:nil];
- [center removeObserver:self name:CTAssetsPickerDidSelectAssetNotification object:nil];
- [center removeObserver:self name:CTAssetsPickerDidDeselectAssetNotification object:nil];
- }
- #pragma mark - Photo library change observer
- - (void)registerChangeObserver
- {
- [[PHPhotoLibrary sharedPhotoLibrary] registerChangeObserver:self];
- }
- - (void)unregisterChangeObserver
- {
- [[PHPhotoLibrary sharedPhotoLibrary] unregisterChangeObserver:self];
- }
- #pragma mark - Photo library changed
- - (void)photoLibraryDidChange:(PHChange *)changeInstance
- {
- // Call might come on any background queue. Re-dispatch to the main queue to handle it.
- dispatch_async(dispatch_get_main_queue(), ^{
-
- PHFetchResultChangeDetails *changeDetails = [changeInstance changeDetailsForFetchResult:self.fetchResult];
-
- if (changeDetails)
- {
- self.fetchResult = changeDetails.fetchResultAfterChanges;
-
- UICollectionView *collectionView = self.collectionView;
-
- if (!changeDetails.hasIncrementalChanges || changeDetails.hasMoves)
- {
- [collectionView reloadData];
- [self resetCachedAssetImages];
- }
- else
- {
- NSArray *removedPaths;
- NSArray *insertedPaths;
- NSArray *changedPaths;
-
- NSIndexSet *removedIndexes = changeDetails.removedIndexes;
- removedPaths = [removedIndexes ctassetsPickerIndexPathsFromIndexesWithSection:0];
-
- NSIndexSet *insertedIndexes = changeDetails.insertedIndexes;
- insertedPaths = [insertedIndexes ctassetsPickerIndexPathsFromIndexesWithSection:0];
-
- NSIndexSet *changedIndexes = changeDetails.changedIndexes;
- changedPaths = [changedIndexes ctassetsPickerIndexPathsFromIndexesWithSection:0];
-
- BOOL shouldReload = NO;
-
- if (changedPaths != nil && removedPaths != nil)
- {
- for (NSIndexPath *changedPath in changedPaths)
- {
- if ([removedPaths containsObject:changedPath])
- {
- shouldReload = YES;
- break;
- }
- }
- }
-
- if (removedPaths.lastObject && ((NSIndexPath *)removedPaths.lastObject).item >= self.fetchResult.count)
- {
- shouldReload = YES;
- }
-
- if (shouldReload)
- {
- [collectionView reloadData];
-
- }
- else
- {
- // if we have incremental diffs, tell the collection view to animate insertions and deletions
- [collectionView performBatchUpdates:^{
- if (removedPaths.count)
- {
- [collectionView deleteItemsAtIndexPaths:[removedIndexes ctassetsPickerIndexPathsFromIndexesWithSection:0]];
- }
-
- if (insertedPaths.count)
- {
- [collectionView insertItemsAtIndexPaths:[insertedIndexes ctassetsPickerIndexPathsFromIndexesWithSection:0]];
- }
-
- if (changedPaths.count)
- {
- [collectionView reloadItemsAtIndexPaths:[changedIndexes ctassetsPickerIndexPathsFromIndexesWithSection:0] ];
- }
- } completion:^(BOOL finished){
- if (finished)
- [self resetCachedAssetImages];
- }];
- }
- }
-
- [self.footer bind:self.fetchResult];
-
- if (self.fetchResult.count == 0)
- [self showNoAssets];
- else
- [self hideNoAssets];
- }
-
- if ([self.delegate respondsToSelector:@selector(assetsGridViewController:photoLibraryDidChangeForAssetCollection:)])
- [self.delegate assetsGridViewController:self photoLibraryDidChangeForAssetCollection:self.assetCollection];
-
- });
- }
- #pragma mark - Selected assets changed
- - (void)assetsPickerSelectedAssetsDidChange:(NSNotification *)notification
- {
- NSArray *selectedAssets = (NSArray *)notification.object;
- [self updateTitle:selectedAssets];
- [self updateButton:selectedAssets];
- }
- - (void)updateTitle:(NSArray *)selectedAssets
- {
- if (selectedAssets.count > 0)
- self.title = self.picker.selectedAssetsString;
- else
- self.title = self.assetCollection.localizedTitle;
- }
- - (void)updateButton:(NSArray *)selectedAssets
- {
- if (self.picker.alwaysEnableDoneButton)
- self.navigationItem.rightBarButtonItem.enabled = YES;
- else
- self.navigationItem.rightBarButtonItem.enabled = (self.picker.selectedAssets.count > 0);
- }
- #pragma mark - Did de/select asset notifications
- - (void)assetsPickerDidSelectAsset:(NSNotification *)notification
- {
- PHAsset *asset = (PHAsset *)notification.object;
- NSIndexPath *indexPath = [NSIndexPath indexPathForItem:[self.fetchResult indexOfObject:asset] inSection:0];
- [self.collectionView selectItemAtIndexPath:indexPath animated:NO scrollPosition:UICollectionViewScrollPositionNone];
-
- [self updateSelectionOrderLabels];
- }
- - (void)assetsPickerDidDeselectAsset:(NSNotification *)notification
- {
- PHAsset *asset = (PHAsset *)notification.object;
- NSIndexPath *indexPath = [NSIndexPath indexPathForItem:[self.fetchResult indexOfObject:asset] inSection:0];
- [self.collectionView deselectItemAtIndexPath:indexPath animated:NO];
-
- [self updateSelectionOrderLabels];
- }
- #pragma mark - Update Selection Order Labels
- - (void)updateSelectionOrderLabels
- {
- for (NSIndexPath *indexPath in [self.collectionView indexPathsForSelectedItems])
- {
- PHAsset *asset = [self assetAtIndexPath:indexPath];
- CTAssetsGridViewCell *cell = (CTAssetsGridViewCell *)[self.collectionView cellForItemAtIndexPath:indexPath];
- cell.selectionIndex = [self.picker.selectedAssets indexOfObject:asset];
- }
- }
- #pragma mark - Gesture recognizer
- - (void)addGestureRecognizer
- {
- UILongPressGestureRecognizer *longPress =
- [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(pushPageViewController:)];
-
- [self.collectionView addGestureRecognizer:longPress];
- }
- #pragma mark - Push assets page view controller
- - (void)pushPageViewController:(UILongPressGestureRecognizer *)longPress
- {
- if (longPress.state == UIGestureRecognizerStateBegan)
- {
- CGPoint point = [longPress locationInView:self.collectionView];
- NSIndexPath *indexPath = [self.collectionView indexPathForItemAtPoint:point];
-
- CTAssetsPageViewController *vc = [[CTAssetsPageViewController alloc] initWithFetchResult:self.fetchResult];
- vc.allowsSelection = YES;
- vc.pageIndex = indexPath.item;
-
- [self.navigationController pushViewController:vc animated:YES];
- }
- }
- #pragma mark - Reload data
- - (void)reloadData
- {
- if (self.fetchResult.count > 0)
- {
- [self hideNoAssets];
- [self.collectionView reloadData];
- }
- else
- {
- [self showNoAssets];
- }
- }
- #pragma mark - Asset images caching
- - (void)resetCachedAssetImages
- {
- [self.imageManager stopCachingImagesForAllAssets];
- self.previousPreheatRect = CGRectZero;
- }
- - (void)updateCachedAssetImages
- {
- BOOL isViewVisible = [self isViewLoaded] && self.view.window != nil;
-
- if (!isViewVisible)
- return;
-
- // The preheat window is twice the height of the visible rect
- CGRect preheatRect = self.collectionView.bounds;
- preheatRect = CGRectInset(preheatRect, 0.0f, -0.5f * CGRectGetHeight(preheatRect));
-
- // If scrolled by a "reasonable" amount...
- CGFloat delta = ABS(CGRectGetMidY(preheatRect) - CGRectGetMidY(self.previousPreheatRect));
-
- if (delta > CGRectGetHeight(self.collectionView.bounds) / 3.0f)
- {
- // Compute the assets to start caching and to stop caching.
- NSMutableArray *addedIndexPaths = [NSMutableArray array];
- NSMutableArray *removedIndexPaths = [NSMutableArray array];
-
- [self computeDifferenceBetweenRect:self.previousPreheatRect
- andRect:preheatRect
- removedHandler:^(CGRect removedRect) {
- NSArray *indexPaths = [self.collectionView ctassetsPickerIndexPathsForElementsInRect:removedRect];
- [removedIndexPaths addObjectsFromArray:indexPaths];
- } addedHandler:^(CGRect addedRect) {
- NSArray *indexPaths = [self.collectionView ctassetsPickerIndexPathsForElementsInRect:addedRect];
- [addedIndexPaths addObjectsFromArray:indexPaths];
- }];
-
- [self startCachingThumbnailsForIndexPaths:addedIndexPaths];
- [self stopCachingThumbnailsForIndexPaths:removedIndexPaths];
-
- self.previousPreheatRect = preheatRect;
- }
- }
- - (void)startCachingThumbnailsForIndexPaths:(NSArray *)indexPaths
- {
- for (NSIndexPath *indexPath in indexPaths)
- {
- PHAsset *asset = [self assetAtIndexPath:indexPath];
-
- if (!asset) break;
-
- UICollectionViewLayoutAttributes *attributes =
- [self.collectionView.collectionViewLayout layoutAttributesForItemAtIndexPath:indexPath];
-
- CGSize targetSize = [self.picker imageSizeForContainerSize:attributes.size];
-
- [self.imageManager startCachingImagesForAssets:@[asset]
- targetSize:targetSize
- contentMode:PHImageContentModeAspectFill
- options:self.picker.thumbnailRequestOptions];
- }
- }
- - (void)stopCachingThumbnailsForIndexPaths:(NSArray *)indexPaths
- {
- for (NSIndexPath *indexPath in indexPaths)
- {
- PHAsset *asset = [self assetAtIndexPath:indexPath];
-
- if (!asset) break;
- UICollectionViewLayoutAttributes *attributes =
- [self.collectionView.collectionViewLayout layoutAttributesForItemAtIndexPath:indexPath];
-
- CGSize targetSize = [self.picker imageSizeForContainerSize:attributes.size];
-
- [self.imageManager stopCachingImagesForAssets:@[asset]
- targetSize:targetSize
- contentMode:PHImageContentModeAspectFill
- options:self.picker.thumbnailRequestOptions];
- }
- }
- - (void)computeDifferenceBetweenRect:(CGRect)oldRect andRect:(CGRect)newRect removedHandler:(void (^)(CGRect removedRect))removedHandler addedHandler:(void (^)(CGRect addedRect))addedHandler
- {
- if (CGRectIntersectsRect(newRect, oldRect)) {
- CGFloat oldMaxY = CGRectGetMaxY(oldRect);
- CGFloat oldMinY = CGRectGetMinY(oldRect);
- CGFloat newMaxY = CGRectGetMaxY(newRect);
- CGFloat newMinY = CGRectGetMinY(newRect);
- if (newMaxY > oldMaxY) {
- CGRect rectToAdd = CGRectMake(newRect.origin.x, oldMaxY, newRect.size.width, (newMaxY - oldMaxY));
- addedHandler(rectToAdd);
- }
- if (oldMinY > newMinY) {
- CGRect rectToAdd = CGRectMake(newRect.origin.x, newMinY, newRect.size.width, (oldMinY - newMinY));
- addedHandler(rectToAdd);
- }
- if (newMaxY < oldMaxY) {
- CGRect rectToRemove = CGRectMake(newRect.origin.x, newMaxY, newRect.size.width, (oldMaxY - newMaxY));
- removedHandler(rectToRemove);
- }
- if (oldMinY < newMinY) {
- CGRect rectToRemove = CGRectMake(newRect.origin.x, oldMinY, newRect.size.width, (newMinY - oldMinY));
- removedHandler(rectToRemove);
- }
- } else {
- addedHandler(newRect);
- removedHandler(oldRect);
- }
- }
- #pragma mark - Scroll view delegate
- - (void)scrollViewDidScroll:(UIScrollView *)scrollView
- {
- [self updateCachedAssetImages];
- }
- #pragma mark - No assets
- - (void)showNoAssets
- {
- CTAssetsPickerNoAssetsView *view = [CTAssetsPickerNoAssetsView new];
- [self.view addSubview:view];
- [view setNeedsUpdateConstraints];
- [view updateConstraintsIfNeeded];
-
- self.noAssetsView = view;
- }
- - (void)hideNoAssets
- {
- if (self.noAssetsView)
- {
- [self.noAssetsView removeFromSuperview];
- self.noAssetsView = nil;
- }
- }
- #pragma mark - Collection view data source
- - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
- {
- return 1;
- }
- - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
- {
- return self.fetchResult.count;
- }
- - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
- {
- CTAssetsGridViewCell *cell =
- [collectionView dequeueReusableCellWithReuseIdentifier:CTAssetsGridViewCellIdentifier
- forIndexPath:indexPath];
-
- PHAsset *asset = [self assetAtIndexPath:indexPath];
-
- if ([self.picker.delegate respondsToSelector:@selector(assetsPickerController:shouldEnableAsset:)])
- cell.enabled = [self.picker.delegate assetsPickerController:self.picker shouldEnableAsset:asset];
- else
- cell.enabled = YES;
-
- cell.showsSelectionIndex = self.picker.showsSelectionIndex;
-
- // XXX
- // Setting `selected` property blocks further deselection.
- // Have to call selectItemAtIndexPath too. ( ref: http://stackoverflow.com/a/17812116/1648333 )
- if ([self.picker.selectedAssets containsObject:asset])
- {
- cell.selected = YES;
- cell.selectionIndex = [self.picker.selectedAssets indexOfObject:asset];
- [collectionView selectItemAtIndexPath:indexPath animated:NO scrollPosition:UICollectionViewScrollPositionNone];
- }
-
- [cell bind:asset];
-
- UICollectionViewLayoutAttributes *attributes =
- [collectionView.collectionViewLayout layoutAttributesForItemAtIndexPath:indexPath];
-
- CGSize targetSize = [self.picker imageSizeForContainerSize:attributes.size];
-
- [self requestThumbnailForCell:cell targetSize:targetSize asset:asset];
- return cell;
- }
- - (void)requestThumbnailForCell:(CTAssetsGridViewCell *)cell targetSize:(CGSize)targetSize asset:(PHAsset *)asset
- {
- NSInteger tag = cell.tag + 1;
- cell.tag = tag;
- [self.imageManager ctassetsPickerRequestImageForAsset:asset
- targetSize:targetSize
- contentMode:PHImageContentModeAspectFill
- options:self.picker.thumbnailRequestOptions
- resultHandler:^(UIImage *image, NSDictionary *info){
- // Only update the image if the cell tag hasn't changed. Otherwise, the cell has been re-used.
- if (cell.tag == tag)
- [(CTAssetThumbnailView *)cell.backgroundView bind:image asset:asset];
- }];
- }
- - (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
- {
- CTAssetsGridViewFooter *footer =
- [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionFooter
- withReuseIdentifier:CTAssetsGridViewFooterIdentifier
- forIndexPath:indexPath];
-
- [footer bind:self.fetchResult];
-
- self.footer = footer;
-
- return footer;
- }
- #pragma mark - Collection view delegate
- - (BOOL)collectionView:(UICollectionView *)collectionView shouldSelectItemAtIndexPath:(NSIndexPath *)indexPath
- {
- PHAsset *asset = [self assetAtIndexPath:indexPath];
-
- CTAssetsGridViewCell *cell = (CTAssetsGridViewCell *)[collectionView cellForItemAtIndexPath:indexPath];
-
- if (!cell.isEnabled)
- return NO;
- else if ([self.picker.delegate respondsToSelector:@selector(assetsPickerController:shouldSelectAsset:)])
- return [self.picker.delegate assetsPickerController:self.picker shouldSelectAsset:asset];
- else
- return YES;
- }
- - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
- {
- PHAsset *asset = [self assetAtIndexPath:indexPath];
-
- [self.picker selectAsset:asset];
-
- if ([self.picker.delegate respondsToSelector:@selector(assetsPickerController:didSelectAsset:)])
- [self.picker.delegate assetsPickerController:self.picker didSelectAsset:asset];
- }
- - (BOOL)collectionView:(UICollectionView *)collectionView shouldDeselectItemAtIndexPath:(NSIndexPath *)indexPath
- {
- PHAsset *asset = [self assetAtIndexPath:indexPath];
-
- if ([self.picker.delegate respondsToSelector:@selector(assetsPickerController:shouldDeselectAsset:)])
- return [self.picker.delegate assetsPickerController:self.picker shouldDeselectAsset:asset];
- else
- return YES;
- }
- - (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath
- {
- PHAsset *asset = [self assetAtIndexPath:indexPath];
-
- [self.picker deselectAsset:asset];
-
- if ([self.picker.delegate respondsToSelector:@selector(assetsPickerController:didDeselectAsset:)])
- [self.picker.delegate assetsPickerController:self.picker didDeselectAsset:asset];
- }
- - (BOOL)collectionView:(UICollectionView *)collectionView shouldHighlightItemAtIndexPath:(NSIndexPath *)indexPath
- {
- PHAsset *asset = [self assetAtIndexPath:indexPath];
-
- if ([self.picker.delegate respondsToSelector:@selector(assetsPickerController:shouldHighlightAsset:)])
- return [self.picker.delegate assetsPickerController:self.picker shouldHighlightAsset:asset];
- else
- return YES;
- }
- - (void)collectionView:(UICollectionView *)collectionView didHighlightItemAtIndexPath:(NSIndexPath *)indexPath
- {
- PHAsset *asset = [self assetAtIndexPath:indexPath];
-
- if ([self.picker.delegate respondsToSelector:@selector(assetsPickerController:didHighlightAsset:)])
- [self.picker.delegate assetsPickerController:self.picker didHighlightAsset:asset];
- }
- - (void)collectionView:(UICollectionView *)collectionView didUnhighlightItemAtIndexPath:(NSIndexPath *)indexPath
- {
- PHAsset *asset = [self assetAtIndexPath:indexPath];
-
- if ([self.picker.delegate respondsToSelector:@selector(assetsPickerController:didUnhighlightAsset:)])
- [self.picker.delegate assetsPickerController:self.picker didUnhighlightAsset:asset];
- }
- @end
|