123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661 |
- //
- // QBAssetsViewController.m
- // QBImagePicker
- //
- // Created by Katsuma Tanaka on 2015/04/03.
- // Copyright (c) 2015 Katsuma Tanaka. All rights reserved.
- //
- #import "QBAssetsViewController.h"
- #import <Photos/Photos.h>
- // Views
- #import "QBImagePickerController.h"
- #import "QBAssetCell.h"
- #import "QBVideoIndicatorView.h"
- static CGSize CGSizeScale(CGSize size, CGFloat scale) {
- return CGSizeMake(size.width * scale, size.height * scale);
- }
- @interface QBImagePickerController (Private)
- @property (nonatomic, strong) NSBundle *assetBundle;
- @end
- @implementation NSIndexSet (Convenience)
- - (NSArray *)qb_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
- @implementation UICollectionView (Convenience)
- - (NSArray *)qb_indexPathsForElementsInRect:(CGRect)rect
- {
- NSArray *allLayoutAttributes = [self.collectionViewLayout layoutAttributesForElementsInRect:rect];
- if (allLayoutAttributes.count == 0) { return nil; }
-
- NSMutableArray *indexPaths = [NSMutableArray arrayWithCapacity:allLayoutAttributes.count];
- for (UICollectionViewLayoutAttributes *layoutAttributes in allLayoutAttributes) {
- NSIndexPath *indexPath = layoutAttributes.indexPath;
- [indexPaths addObject:indexPath];
- }
- return indexPaths;
- }
- @end
- @interface QBAssetsViewController () <PHPhotoLibraryChangeObserver, UICollectionViewDelegateFlowLayout>
- @property (nonatomic, strong) IBOutlet UIBarButtonItem *doneButton;
- @property (nonatomic, strong) PHFetchResult *fetchResult;
- @property (nonatomic, strong) PHCachingImageManager *imageManager;
- @property (nonatomic, assign) CGRect previousPreheatRect;
- @property (nonatomic, assign) BOOL disableScrollToBottom;
- @property (nonatomic, strong) NSIndexPath *lastSelectedItemIndexPath;
- @end
- @implementation QBAssetsViewController
- - (void)viewDidLoad
- {
- [super viewDidLoad];
-
- [self setUpToolbarItems];
- [self resetCachedAssets];
-
- // Register observer
- [[PHPhotoLibrary sharedPhotoLibrary] registerChangeObserver:self];
- }
- - (void)viewWillAppear:(BOOL)animated
- {
- [super viewWillAppear:animated];
-
- // Configure navigation item
- self.navigationItem.title = self.assetCollection.localizedTitle;
- self.navigationItem.prompt = self.imagePickerController.prompt;
-
- // Configure collection view
- self.collectionView.allowsMultipleSelection = self.imagePickerController.allowsMultipleSelection;
-
- // Show/hide 'Done' button
- if (self.imagePickerController.allowsMultipleSelection) {
- [self.navigationItem setRightBarButtonItem:self.doneButton animated:NO];
- } else {
- [self.navigationItem setRightBarButtonItem:nil animated:NO];
- }
-
- [self updateDoneButtonState];
- [self updateSelectionInfo];
- [self.collectionView reloadData];
-
- // Scroll to bottom
- if (self.fetchResult.count > 0 && self.isMovingToParentViewController && !self.disableScrollToBottom) {
- NSIndexPath *indexPath = [NSIndexPath indexPathForItem:(self.fetchResult.count - 1) inSection:0];
- [self.collectionView scrollToItemAtIndexPath:indexPath atScrollPosition:UICollectionViewScrollPositionTop animated:NO];
- }
- }
- - (void)viewWillDisappear:(BOOL)animated
- {
- [super viewWillDisappear:animated];
-
- self.disableScrollToBottom = YES;
- }
- - (void)viewDidAppear:(BOOL)animated
- {
- [super viewDidAppear:animated];
-
- self.disableScrollToBottom = NO;
-
- [self updateCachedAssets];
- }
- - (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
- {
- // Save indexPath for the last item
- NSIndexPath *indexPath = [[self.collectionView indexPathsForVisibleItems] lastObject];
-
- // Update layout
- [self.collectionViewLayout invalidateLayout];
-
- // Restore scroll position
- [coordinator animateAlongsideTransition:nil completion:^(id<UIViewControllerTransitionCoordinatorContext> context) {
- [self.collectionView scrollToItemAtIndexPath:indexPath atScrollPosition:UICollectionViewScrollPositionBottom animated:NO];
- }];
- }
- - (void)dealloc
- {
- // Deregister observer
- [[PHPhotoLibrary sharedPhotoLibrary] unregisterChangeObserver:self];
- }
- #pragma mark - Accessors
- - (void)setAssetCollection:(PHAssetCollection *)assetCollection
- {
- _assetCollection = assetCollection;
-
- [self updateFetchRequest];
- [self.collectionView reloadData];
- }
- - (PHCachingImageManager *)imageManager
- {
- if (_imageManager == nil) {
- _imageManager = [PHCachingImageManager new];
- }
-
- return _imageManager;
- }
- - (BOOL)isAutoDeselectEnabled
- {
- return (self.imagePickerController.maximumNumberOfSelection == 1
- && self.imagePickerController.maximumNumberOfSelection >= self.imagePickerController.minimumNumberOfSelection);
- }
- #pragma mark - Actions
- - (IBAction)done:(id)sender
- {
- if ([self.imagePickerController.delegate respondsToSelector:@selector(qb_imagePickerController:didFinishPickingAssets:)]) {
- [self.imagePickerController.delegate qb_imagePickerController:self.imagePickerController
- didFinishPickingAssets:self.imagePickerController.selectedAssets.array];
- }
- }
- #pragma mark - Toolbar
- - (void)setUpToolbarItems
- {
- // Space
- UIBarButtonItem *leftSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:NULL];
- UIBarButtonItem *rightSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:NULL];
-
- // Info label
- NSDictionary *attributes = @{ NSForegroundColorAttributeName: [UIColor blackColor] };
- UIBarButtonItem *infoButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStylePlain target:nil action:NULL];
- infoButtonItem.enabled = NO;
- [infoButtonItem setTitleTextAttributes:attributes forState:UIControlStateNormal];
- [infoButtonItem setTitleTextAttributes:attributes forState:UIControlStateDisabled];
-
- self.toolbarItems = @[leftSpace, infoButtonItem, rightSpace];
- }
- - (void)updateSelectionInfo
- {
- NSMutableOrderedSet *selectedAssets = self.imagePickerController.selectedAssets;
-
- if (selectedAssets.count > 0) {
- NSBundle *bundle = self.imagePickerController.assetBundle;
- NSString *format;
- if (selectedAssets.count > 1) {
- format = NSLocalizedStringFromTableInBundle(@"assets.toolbar.items-selected", @"QBImagePicker", bundle, nil);
- } else {
- format = NSLocalizedStringFromTableInBundle(@"assets.toolbar.item-selected", @"QBImagePicker", bundle, nil);
- }
-
- NSString *title = [NSString stringWithFormat:format, selectedAssets.count];
- [(UIBarButtonItem *)self.toolbarItems[1] setTitle:title];
- } else {
- [(UIBarButtonItem *)self.toolbarItems[1] setTitle:@""];
- }
- }
- #pragma mark - Fetching Assets
- - (void)updateFetchRequest
- {
- if (self.assetCollection) {
- PHFetchOptions *options = [PHFetchOptions new];
-
- switch (self.imagePickerController.mediaType) {
- case QBImagePickerMediaTypeImage:
- options.predicate = [NSPredicate predicateWithFormat:@"mediaType == %ld", PHAssetMediaTypeImage];
- break;
-
- case QBImagePickerMediaTypeVideo:
- options.predicate = [NSPredicate predicateWithFormat:@"mediaType == %ld", PHAssetMediaTypeVideo];
- break;
-
- default:
- break;
- }
-
- self.fetchResult = [PHAsset fetchAssetsInAssetCollection:self.assetCollection options:options];
-
- if ([self isAutoDeselectEnabled] && self.imagePickerController.selectedAssets.count > 0) {
- // Get index of previous selected asset
- PHAsset *asset = [self.imagePickerController.selectedAssets firstObject];
- NSInteger assetIndex = [self.fetchResult indexOfObject:asset];
- self.lastSelectedItemIndexPath = [NSIndexPath indexPathForItem:assetIndex inSection:0];
- }
- } else {
- self.fetchResult = nil;
- }
- }
- #pragma mark - Checking for Selection Limit
- - (BOOL)isMinimumSelectionLimitFulfilled
- {
- return (self.imagePickerController.minimumNumberOfSelection <= self.imagePickerController.selectedAssets.count);
- }
- - (BOOL)isMaximumSelectionLimitReached
- {
- NSUInteger minimumNumberOfSelection = MAX(1, self.imagePickerController.minimumNumberOfSelection);
-
- if (minimumNumberOfSelection <= self.imagePickerController.maximumNumberOfSelection) {
- return (self.imagePickerController.maximumNumberOfSelection <= self.imagePickerController.selectedAssets.count);
- }
-
- return NO;
- }
- - (void)updateDoneButtonState
- {
- self.doneButton.enabled = [self isMinimumSelectionLimitFulfilled];
- }
- #pragma mark - Asset Caching
- - (void)resetCachedAssets
- {
- [self.imageManager stopCachingImagesForAllAssets];
- self.previousPreheatRect = CGRectZero;
- }
- - (void)updateCachedAssets
- {
- 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.0, -0.5 * CGRectGetHeight(preheatRect));
-
- // If scrolled by a "reasonable" amount...
- CGFloat delta = ABS(CGRectGetMidY(preheatRect) - CGRectGetMidY(self.previousPreheatRect));
-
- if (delta > CGRectGetHeight(self.collectionView.bounds) / 3.0) {
- // Compute the assets to start caching and to stop caching
- NSMutableArray *addedIndexPaths = [NSMutableArray array];
- NSMutableArray *removedIndexPaths = [NSMutableArray array];
-
- [self computeDifferenceBetweenRect:self.previousPreheatRect andRect:preheatRect addedHandler:^(CGRect addedRect) {
- NSArray *indexPaths = [self.collectionView qb_indexPathsForElementsInRect:addedRect];
- [addedIndexPaths addObjectsFromArray:indexPaths];
- } removedHandler:^(CGRect removedRect) {
- NSArray *indexPaths = [self.collectionView qb_indexPathsForElementsInRect:removedRect];
- [removedIndexPaths addObjectsFromArray:indexPaths];
- }];
-
- NSArray *assetsToStartCaching = [self assetsAtIndexPaths:addedIndexPaths];
- NSArray *assetsToStopCaching = [self assetsAtIndexPaths:removedIndexPaths];
-
- CGSize itemSize = [(UICollectionViewFlowLayout *)self.collectionViewLayout itemSize];
- CGSize targetSize = CGSizeScale(itemSize, self.traitCollection.displayScale);
-
- [self.imageManager startCachingImagesForAssets:assetsToStartCaching
- targetSize:targetSize
- contentMode:PHImageContentModeAspectFill
- options:nil];
- [self.imageManager stopCachingImagesForAssets:assetsToStopCaching
- targetSize:targetSize
- contentMode:PHImageContentModeAspectFill
- options:nil];
-
- self.previousPreheatRect = preheatRect;
- }
- }
- - (void)computeDifferenceBetweenRect:(CGRect)oldRect andRect:(CGRect)newRect addedHandler:(void (^)(CGRect addedRect))addedHandler removedHandler:(void (^)(CGRect removedRect))removedHandler
- {
- 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);
- }
- }
- - (NSArray *)assetsAtIndexPaths:(NSArray *)indexPaths
- {
- if (indexPaths.count == 0) { return nil; }
-
- NSMutableArray *assets = [NSMutableArray arrayWithCapacity:indexPaths.count];
- for (NSIndexPath *indexPath in indexPaths) {
- if (indexPath.item < self.fetchResult.count) {
- PHAsset *asset = self.fetchResult[indexPath.item];
- [assets addObject:asset];
- }
- }
- return assets;
- }
- #pragma mark - PHPhotoLibraryChangeObserver
- - (void)photoLibraryDidChange:(PHChange *)changeInstance
- {
- dispatch_async(dispatch_get_main_queue(), ^{
- PHFetchResultChangeDetails *collectionChanges = [changeInstance changeDetailsForFetchResult:self.fetchResult];
-
- if (collectionChanges) {
- // Get the new fetch result
- self.fetchResult = [collectionChanges fetchResultAfterChanges];
-
- if (![collectionChanges hasIncrementalChanges] || [collectionChanges hasMoves]) {
- // We need to reload all if the incremental diffs are not available
- [self.collectionView reloadData];
- } else {
- // If we have incremental diffs, tell the collection view to animate insertions and deletions
- [self.collectionView performBatchUpdates:^{
- NSIndexSet *removedIndexes = [collectionChanges removedIndexes];
- if ([removedIndexes count]) {
- [self.collectionView deleteItemsAtIndexPaths:[removedIndexes qb_indexPathsFromIndexesWithSection:0]];
- }
-
- NSIndexSet *insertedIndexes = [collectionChanges insertedIndexes];
- if ([insertedIndexes count]) {
- [self.collectionView insertItemsAtIndexPaths:[insertedIndexes qb_indexPathsFromIndexesWithSection:0]];
- }
-
- NSIndexSet *changedIndexes = [collectionChanges changedIndexes];
- if ([changedIndexes count]) {
- [self.collectionView reloadItemsAtIndexPaths:[changedIndexes qb_indexPathsFromIndexesWithSection:0]];
- }
- } completion:NULL];
- }
-
- [self resetCachedAssets];
- }
- });
- }
- #pragma mark - UIScrollViewDelegate
- - (void)scrollViewDidScroll:(UIScrollView *)scrollView
- {
- [self updateCachedAssets];
- }
- #pragma mark - UICollectionViewDataSource
- - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
- {
- return 1;
- }
- - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
- {
- return self.fetchResult.count;
- }
- - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
- {
- QBAssetCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"AssetCell" forIndexPath:indexPath];
- cell.tag = indexPath.item;
- cell.showsOverlayViewWhenSelected = self.imagePickerController.allowsMultipleSelection;
-
- // Image
- PHAsset *asset = self.fetchResult[indexPath.item];
- CGSize itemSize = [(UICollectionViewFlowLayout *)collectionView.collectionViewLayout itemSize];
- CGSize targetSize = CGSizeScale(itemSize, self.traitCollection.displayScale);
-
- [self.imageManager requestImageForAsset:asset
- targetSize:targetSize
- contentMode:PHImageContentModeAspectFill
- options:nil
- resultHandler:^(UIImage *result, NSDictionary *info) {
- if (cell.tag == indexPath.item) {
- cell.imageView.image = result;
- }
- }];
-
- // Video indicator
- if (asset.mediaType == PHAssetMediaTypeVideo) {
- cell.videoIndicatorView.hidden = NO;
-
- NSInteger minutes = (NSInteger)(asset.duration / 60.0);
- NSInteger seconds = (NSInteger)ceil(asset.duration - 60.0 * (double)minutes);
- cell.videoIndicatorView.timeLabel.text = [NSString stringWithFormat:@"%02ld:%02ld", (long)minutes, (long)seconds];
-
- if (asset.mediaSubtypes & PHAssetMediaSubtypeVideoHighFrameRate) {
- cell.videoIndicatorView.videoIcon.hidden = YES;
- cell.videoIndicatorView.slomoIcon.hidden = NO;
- }
- else {
- cell.videoIndicatorView.videoIcon.hidden = NO;
- cell.videoIndicatorView.slomoIcon.hidden = YES;
- }
- } else {
- cell.videoIndicatorView.hidden = YES;
- }
-
- // Selection state
- if ([self.imagePickerController.selectedAssets containsObject:asset]) {
- [cell setSelected:YES];
- [collectionView selectItemAtIndexPath:indexPath animated:NO scrollPosition:UICollectionViewScrollPositionNone];
- }
-
- return cell;
- }
- - (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView viewForSupplementaryElementOfKind:(NSString *)kind atIndexPath:(NSIndexPath *)indexPath
- {
- if (kind == UICollectionElementKindSectionFooter) {
- UICollectionReusableView *footerView = [collectionView dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionFooter
- withReuseIdentifier:@"FooterView"
- forIndexPath:indexPath];
-
- // Number of assets
- UILabel *label = (UILabel *)[footerView viewWithTag:1];
-
- NSBundle *bundle = self.imagePickerController.assetBundle;
- NSUInteger numberOfPhotos = [self.fetchResult countOfAssetsWithMediaType:PHAssetMediaTypeImage];
- NSUInteger numberOfVideos = [self.fetchResult countOfAssetsWithMediaType:PHAssetMediaTypeVideo];
-
- switch (self.imagePickerController.mediaType) {
- case QBImagePickerMediaTypeAny:
- {
- NSString *format;
- if (numberOfPhotos == 1) {
- if (numberOfVideos == 1) {
- format = NSLocalizedStringFromTableInBundle(@"assets.footer.photo-and-video", @"QBImagePicker", bundle, nil);
- } else {
- format = NSLocalizedStringFromTableInBundle(@"assets.footer.photo-and-videos", @"QBImagePicker", bundle, nil);
- }
- } else if (numberOfVideos == 1) {
- format = NSLocalizedStringFromTableInBundle(@"assets.footer.photos-and-video", @"QBImagePicker", bundle, nil);
- } else {
- format = NSLocalizedStringFromTableInBundle(@"assets.footer.photos-and-videos", @"QBImagePicker", bundle, nil);
- }
-
- label.text = [NSString stringWithFormat:format, numberOfPhotos, numberOfVideos];
- }
- break;
-
- case QBImagePickerMediaTypeImage:
- {
- NSString *key = (numberOfPhotos == 1) ? @"assets.footer.photo" : @"assets.footer.photos";
- NSString *format = NSLocalizedStringFromTableInBundle(key, @"QBImagePicker", bundle, nil);
-
- label.text = [NSString stringWithFormat:format, numberOfPhotos];
- }
- break;
-
- case QBImagePickerMediaTypeVideo:
- {
- NSString *key = (numberOfVideos == 1) ? @"assets.footer.video" : @"assets.footer.videos";
- NSString *format = NSLocalizedStringFromTableInBundle(key, @"QBImagePicker", bundle, nil);
-
- label.text = [NSString stringWithFormat:format, numberOfVideos];
- }
- break;
- }
-
- return footerView;
- }
-
- return nil;
- }
- #pragma mark - UICollectionViewDelegate
- - (BOOL)collectionView:(UICollectionView *)collectionView shouldSelectItemAtIndexPath:(NSIndexPath *)indexPath
- {
- if ([self.imagePickerController.delegate respondsToSelector:@selector(qb_imagePickerController:shouldSelectAsset:)]) {
- PHAsset *asset = self.fetchResult[indexPath.item];
- return [self.imagePickerController.delegate qb_imagePickerController:self.imagePickerController shouldSelectAsset:asset];
- }
-
- if ([self isAutoDeselectEnabled]) {
- return YES;
- }
-
- return ![self isMaximumSelectionLimitReached];
- }
- - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
- {
- QBImagePickerController *imagePickerController = self.imagePickerController;
- NSMutableOrderedSet *selectedAssets = imagePickerController.selectedAssets;
-
- PHAsset *asset = self.fetchResult[indexPath.item];
-
- if (imagePickerController.allowsMultipleSelection) {
- if ([self isAutoDeselectEnabled] && selectedAssets.count > 0) {
- // Remove previous selected asset from set
- [selectedAssets removeObjectAtIndex:0];
-
- // Deselect previous selected asset
- if (self.lastSelectedItemIndexPath) {
- [collectionView deselectItemAtIndexPath:self.lastSelectedItemIndexPath animated:NO];
- }
- }
-
- // Add asset to set
- [selectedAssets addObject:asset];
-
- self.lastSelectedItemIndexPath = indexPath;
-
- [self updateDoneButtonState];
-
- if (imagePickerController.showsNumberOfSelectedAssets) {
- [self updateSelectionInfo];
-
- if (selectedAssets.count == 1) {
- // Show toolbar
- [self.navigationController setToolbarHidden:NO animated:YES];
- }
- }
- } else {
- if ([imagePickerController.delegate respondsToSelector:@selector(qb_imagePickerController:didFinishPickingAssets:)]) {
- [imagePickerController.delegate qb_imagePickerController:imagePickerController didFinishPickingAssets:@[asset]];
- }
- }
-
- if ([imagePickerController.delegate respondsToSelector:@selector(qb_imagePickerController:didSelectAsset:)]) {
- [imagePickerController.delegate qb_imagePickerController:imagePickerController didSelectAsset:asset];
- }
- }
- - (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath
- {
- if (!self.imagePickerController.allowsMultipleSelection) {
- return;
- }
-
- QBImagePickerController *imagePickerController = self.imagePickerController;
- NSMutableOrderedSet *selectedAssets = imagePickerController.selectedAssets;
-
- PHAsset *asset = self.fetchResult[indexPath.item];
-
- // Remove asset from set
- [selectedAssets removeObject:asset];
-
- self.lastSelectedItemIndexPath = nil;
-
- [self updateDoneButtonState];
-
- if (imagePickerController.showsNumberOfSelectedAssets) {
- [self updateSelectionInfo];
-
- if (selectedAssets.count == 0) {
- // Hide toolbar
- [self.navigationController setToolbarHidden:YES animated:YES];
- }
- }
-
- if ([imagePickerController.delegate respondsToSelector:@selector(qb_imagePickerController:didDeselectAsset:)]) {
- [imagePickerController.delegate qb_imagePickerController:imagePickerController didDeselectAsset:asset];
- }
- }
- #pragma mark - UICollectionViewDelegateFlowLayout
- - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
- {
- NSUInteger numberOfColumns;
- if (UIInterfaceOrientationIsPortrait([[UIApplication sharedApplication] statusBarOrientation])) {
- numberOfColumns = self.imagePickerController.numberOfColumnsInPortrait;
- } else {
- numberOfColumns = self.imagePickerController.numberOfColumnsInLandscape;
- }
-
- CGFloat width = (CGRectGetWidth(self.view.frame) - 2.0 * (numberOfColumns - 1)) / numberOfColumns;
-
- return CGSizeMake(width, width);
- }
- @end
|