diff --git a/Pod/Classes/DVGAssetPickerCollectionViewCell.h b/Pod/Classes/DVGAssetPickerCollectionViewCell.h index 6e54414..bee40e7 100644 --- a/Pod/Classes/DVGAssetPickerCollectionViewCell.h +++ b/Pod/Classes/DVGAssetPickerCollectionViewCell.h @@ -11,5 +11,6 @@ @interface DVGAssetPickerCollectionViewCell : UICollectionViewCell @property (weak, nonatomic) UIImageView *imageView; +@property (nonatomic) NSDictionary *userInfo; @end diff --git a/Pod/Classes/DVGAssetPickerViewController.h b/Pod/Classes/DVGAssetPickerViewController.h index 8757a12..e6a189c 100644 --- a/Pod/Classes/DVGAssetPickerViewController.h +++ b/Pod/Classes/DVGAssetPickerViewController.h @@ -7,7 +7,9 @@ // #import -#import +@import Photos; + +NS_ASSUME_NONNULL_BEGIN typedef NS_ENUM(NSUInteger, DVGAssetPickerMenuItem) { DVGAssetPickerMenuItemPhotoLibrary, @@ -20,18 +22,31 @@ typedef NS_ENUM(NSUInteger, DVGAssetPickerMenuItem) { @protocol DVGAssetPickerDelegate - (void)contentPickerViewController:(DVGAssetPickerViewController *)controller - didSelectAssets:(NSArray *)assets; + didSelectAssets:(NSArray *)assets; - (void)contentPickerViewController:(DVGAssetPickerViewController *)controller clickedMenuItem:(DVGAssetPickerMenuItem)menuItem; - (void)contentPickerViewControllerDidCancel:(DVGAssetPickerViewController *)controller; @end + +@protocol DVGAssetPickerDataSource + +@optional +- (NSDictionary *)contentPickerViewController:(DVGAssetPickerViewController *)controller + textAttributesForMenuItem:(DVGAssetPickerMenuItem)menuItem; + +@end + + @interface DVGAssetPickerViewController : UIViewController - (instancetype)init; - (void)cancel; -@property (nonatomic, weak) id delegate; -@property (strong, nonatomic) ALAssetsLibrary *assetsLibrary; +@property (nonatomic, weak) _Nullable id delegate; +@property (nonatomic, weak) _Nullable id dataSource; +@property (strong, nonatomic) PHPhotoLibrary * photoLibrary; @end + +NS_ASSUME_NONNULL_END diff --git a/Pod/Classes/DVGAssetPickerViewController.m b/Pod/Classes/DVGAssetPickerViewController.m index 6f09aee..a1949e4 100644 --- a/Pod/Classes/DVGAssetPickerViewController.m +++ b/Pod/Classes/DVGAssetPickerViewController.m @@ -35,8 +35,8 @@ @interface DVGAssetPickerViewController () @property (weak, nonatomic) UITableView *tableView; @property (weak, nonatomic) UICollectionView *collectionView; @property (weak, nonatomic) NSLayoutConstraint *collectionHeightConstraint; -@property (copy, nonatomic) NSArray *assets; -@property (strong, nonatomic) NSMutableSet *selectedAssets; +@property (copy, nonatomic) PHFetchResult *assets; +@property (strong, nonatomic) NSMutableSet *selectedAssets; @property (nonatomic) BOOL collectionViewExpanded; @end @@ -49,6 +49,7 @@ - (instancetype)init self.modalPresentationStyle = UIModalPresentationCustom; self.transitioningDelegate = self; self.automaticallyAdjustsScrollViewInsets = YES; + self.photoLibrary = [PHPhotoLibrary sharedPhotoLibrary]; } return self; } @@ -57,8 +58,6 @@ - (void)viewDidLoad { [super viewDidLoad]; - self.assetsLibrary = [[ALAssetsLibrary alloc] init]; - self.view.backgroundColor = [UIColor whiteColor]; UICollectionView *collectionView = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:[self newCollectionLayout]]; @@ -147,38 +146,21 @@ - (void)updateViewConstraints #pragma mark - -- (NSArray *)fetchAllAssetsSynchronously +- (PHFetchResult *)fetchAllAssetsSynchronously { - NSMutableArray *assets = [NSMutableArray array]; - dispatch_group_t dispatchGroup = dispatch_group_create(); - - dispatch_group_enter(dispatchGroup); - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ - __block NSInteger maxCount = 50; - [self.assetsLibrary enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos usingBlock:^(ALAssetsGroup *group, BOOL *stopGroups) { - if (group) { - [group enumerateAssetsWithOptions:NSEnumerationReverse usingBlock:^(ALAsset *result, NSUInteger index, BOOL *stopAssets) { - if (result && - [[result valueForProperty:ALAssetPropertyType] isEqualToString:ALAssetTypePhoto]) { - [assets addObject:result]; - maxCount--; - if (maxCount == 0) { - *stopAssets = *stopGroups = YES; - } - } - }]; - } - else { - dispatch_group_leave(dispatchGroup); - } - } failureBlock:^(NSError *error) { - // XXX Handle error - dispatch_group_leave(dispatchGroup); - }]; - }); - dispatch_group_wait(dispatchGroup, DISPATCH_TIME_FOREVER); + PHFetchResult * result = [PHAssetCollection + fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum + subtype:PHAssetCollectionSubtypeSmartAlbumUserLibrary + options:nil]; + if (result.count == 0) { + return @[]; + } - return assets; + PHAssetCollection * collection = result.firstObject; + PHFetchOptions * options = [[PHFetchOptions alloc] init]; + options.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:NO]]; + options.predicate = [NSPredicate predicateWithFormat:@"mediaType == %i", PHAssetMediaTypeImage]; + return [PHAsset fetchAssetsInAssetCollection:collection options:options]; } - (void)cancel @@ -257,11 +239,11 @@ - (void)collectionViewScrollToItemAtIndexPathCentered:(NSIndexPath *)indexPath // doesn't always work correctly (for example, indexPath.row from 1 to 2). UICollectionViewFlowLayout *layout = (id)self.collectionView.collectionViewLayout; - + if ([layout isKindOfClass:[UICollectionViewFlowLayout class]] == false) { return; } - + UIEdgeInsets inset = self.collectionView.contentInset; UIEdgeInsets sectionInset = layout.sectionInset; CGRect frame = [layout layoutAttributesForItemAtIndexPath:indexPath].frame; @@ -287,34 +269,44 @@ - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + DVGAssetPickerMenuItem item = (DVGAssetPickerMenuItem)indexPath.row; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath]; - switch ((DVGAssetPickerMenuItem)indexPath.row) { + NSString * title; + + switch (item) { case DVGAssetPickerMenuItemPhotoLibrary: { NSInteger selectedCount = [self.selectedAssets count]; if (!self.collectionViewExpanded || selectedCount == 0) { - cell.textLabel.text = NSLocalizedString(@"Photo Library", nil); + title = NSLocalizedString(@"Photo Library", nil); } else if (selectedCount == 1) { - cell.textLabel.text = [NSString stringWithFormat:NSLocalizedString(@"Select %d Photo", nil), selectedCount]; + title = [NSString stringWithFormat:NSLocalizedString(@"Select %d Photo", nil), selectedCount]; } else { - cell.textLabel.text = [NSString stringWithFormat:NSLocalizedString(@"Select %d Photos", nil), selectedCount]; + title = [NSString stringWithFormat:NSLocalizedString(@"Select %d Photos", nil), selectedCount]; } break; } case DVGAssetPickerMenuItemCamera: - cell.textLabel.text = NSLocalizedString(@"Take Photo", nil); + title = NSLocalizedString(@"Take Photo", nil); break; case DVGAssetPickerMenuItemCancel: - cell.textLabel.text = NSLocalizedString(@"Cancel", nil); + title = NSLocalizedString(@"Cancel", nil); break; } cell.textLabel.textAlignment = NSTextAlignmentCenter; cell.textLabel.textColor = cell.tintColor; + if ([self.dataSource respondsToSelector:@selector(contentPickerViewController:textAttributesForMenuItem:)]) { + NSDictionary* attributes = [self.dataSource contentPickerViewController:self textAttributesForMenuItem:item]; + cell.textLabel.attributedText = [[NSAttributedString alloc] initWithString:title attributes:attributes]; + }else { + cell.textLabel.text = title; + } + return cell; } @@ -354,11 +346,30 @@ - (NSInteger)collectionView:(UICollectionView *)collectionView - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { - ALAsset *asset = self.assets[indexPath.row]; + PHAsset *asset = self.assets[indexPath.row]; DVGAssetPickerCollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"Cell" forIndexPath:indexPath]; - UIImage *thumbnail = [UIImage imageWithCGImage:[asset aspectRatioThumbnail]]; - cell.imageView.image = thumbnail; + + // cancel previous image fetch if the cell is being reused + if (cell.userInfo && cell.userInfo[@"request_id"]) { + PHImageRequestID requestID = [cell.userInfo[@"request_id"] intValue]; + [[PHImageManager defaultManager] cancelImageRequest:requestID]; + } + + + CGRect screenSize = [[UIScreen mainScreen] nativeBounds]; + CGFloat size1D = MAX(screenSize.size.width, screenSize.size.height); + CGSize targetSize = CGSizeMake(size1D, size1D); + + PHImageRequestOptions * options = [[PHImageRequestOptions alloc] init]; + options.deliveryMode = PHImageRequestOptionsDeliveryModeOpportunistic; + options.resizeMode = PHImageRequestOptionsResizeModeFast; + options.networkAccessAllowed = NO; + + PHImageRequestID requestID = [[PHImageManager defaultManager] requestImageForAsset:asset targetSize:targetSize contentMode:PHImageContentModeAspectFit options:options resultHandler:^(UIImage * _Nullable result, NSDictionary * _Nullable info) { + cell.imageView.image = result; + }]; + cell.userInfo = @{@"request_id": @(requestID)}; return cell; } @@ -369,7 +380,7 @@ - (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView { UICollectionReusableView *view; if ([kind isEqualToString:DVGAssetPickerSupplementaryKindCheckmark]) { - ALAsset *asset = self.assets[indexPath.row]; + PHAsset *asset = self.assets[indexPath.row]; DVGAssetPickerCheckmarkView *checkmark = [collectionView dequeueReusableSupplementaryViewOfKind:kind withReuseIdentifier:@"Checkmark" forIndexPath:indexPath]; checkmark.selected = [self.selectedAssets containsObject:asset]; view = checkmark; @@ -382,7 +393,7 @@ - (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath { - ALAsset *asset = self.assets[indexPath.row]; + PHAsset *asset = self.assets[indexPath.row]; if (!self.collectionViewExpanded) { self.selectedAssets = [NSMutableSet setWithObject:asset]; @@ -426,14 +437,12 @@ - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath { - ALAsset *asset = self.assets[indexPath.row]; - UIImage *thumbnail = [UIImage imageWithCGImage:[asset aspectRatioThumbnail]]; + PHAsset *asset = self.assets[indexPath.row]; CGFloat height = [self collectionViewHeight] - kCollectionViewPadding * 2; CGFloat maxWidth = CGRectGetWidth(self.view.bounds) - kCollectionViewPadding * 2; - CGFloat width = (thumbnail - ? thumbnail.size.width * height / thumbnail.size.height - : height); + CGFloat width = (CGFloat)asset.pixelWidth * height / (CGFloat)asset.pixelHeight; + width = MIN(maxWidth, width); CGSize size = CGSizeMake(width, height);