From cd01625df4481a09f1affbabc2414ff87b7215cc Mon Sep 17 00:00:00 2001 From: "dinesh.kumar" Date: Mon, 11 Sep 2017 18:41:28 +0530 Subject: [PATCH 1/7] Fixed some customizations to defaults. --- Examples/GMPhotoPicker/Info.plist | 2 ++ GMImagePicker/GMImagePickerController.m | 5 ----- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/Examples/GMPhotoPicker/Info.plist b/Examples/GMPhotoPicker/Info.plist index e8e9d53..8fef11e 100644 --- a/Examples/GMPhotoPicker/Info.plist +++ b/Examples/GMPhotoPicker/Info.plist @@ -36,6 +36,8 @@ UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight + NSPhotoLibraryUsageDescription + GMPhotoPicker would like to access you photos. UISupportedInterfaceOrientations~ipad UIInterfaceOrientationPortrait diff --git a/GMImagePicker/GMImagePickerController.m b/GMImagePicker/GMImagePickerController.m index e5b1db7..2be9e2e 100644 --- a/GMImagePicker/GMImagePickerController.m +++ b/GMImagePicker/GMImagePickerController.m @@ -86,7 +86,6 @@ - (void)viewWillAppear:(BOOL)animated _navigationController.toolbar.translucent = YES; _navigationController.toolbar.barTintColor = _toolbarBarTintColor; _navigationController.toolbar.tintColor = _toolbarTintColor; - [(UIView*)[_navigationController.toolbar.subviews objectAtIndex:0] setAlpha:0.75f]; // URGH - I know! _navigationController.navigationBar.backgroundColor = _navigationBarBackgroundColor; _navigationController.navigationBar.tintColor = _navigationBarTintColor; @@ -115,10 +114,6 @@ - (void)setupNavigationController _navigationController = [[UINavigationController alloc] initWithRootViewController:albumsViewController]; _navigationController.delegate = self; - _navigationController.navigationBar.translucent = YES; - [_navigationController.navigationBar setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault]; - _navigationController.navigationBar.shadowImage = [UIImage new]; - [_navigationController willMoveToParentViewController:self]; [_navigationController.view setFrame:self.view.frame]; [self.view addSubview:_navigationController.view]; From b6a742199e234361c527f4463494fc08af50de4b Mon Sep 17 00:00:00 2001 From: "dinesh.kumar" Date: Mon, 18 Sep 2017 12:35:32 +0530 Subject: [PATCH 2/7] Refractored layout of detail text and text labels on Album Cell(there was an issue in iOS 11 without this). Rest some colors back to default. --- GMImagePicker/GMAlbumsViewCell.m | 48 ++++---------------------- GMImagePicker/GMAlbumsViewController.m | 4 +-- 2 files changed, 9 insertions(+), 43 deletions(-) diff --git a/GMImagePicker/GMAlbumsViewCell.m b/GMImagePicker/GMAlbumsViewCell.m index 8976b98..fe45c6b 100644 --- a/GMImagePicker/GMAlbumsViewCell.m +++ b/GMImagePicker/GMAlbumsViewCell.m @@ -16,8 +16,6 @@ @implementation GMAlbumsViewCell - (void)awakeFromNib { [super awakeFromNib]; - self.contentView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; - self.contentView.translatesAutoresizingMaskIntoConstraints = YES; } - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier @@ -25,10 +23,6 @@ - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reus if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) { - self.opaque = NO; - self.backgroundColor = [UIColor clearColor]; - self.textLabel.backgroundColor = self.backgroundColor; - self.detailTextLabel.backgroundColor = self.backgroundColor; // self.isAccessibilityElement = YES; self.accessoryType = UITableViewCellAccessoryDisclosureIndicator; @@ -99,48 +93,20 @@ - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reus // TextLabel self.textLabel.font = [UIFont fontWithName:@"HelveticaNeue" size:17.0]; self.textLabel.numberOfLines = 1; - self.textLabel.translatesAutoresizingMaskIntoConstraints = NO; - self.textLabel.adjustsFontSizeToFitWidth = YES; - + self.detailTextLabel.font = [UIFont fontWithName:@"HelveticaNeue" size:14.0]; self.detailTextLabel.numberOfLines = 1; - self.detailTextLabel.translatesAutoresizingMaskIntoConstraints = NO; - self.detailTextLabel.adjustsFontSizeToFitWidth = YES; - - // Set next text labels contraints : - [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[imageView1]-(offset)-[textLabel]-|" - options:0 - metrics:@{@"offset": @(kAlbumImageToTextSpace)} - views:@{@"textLabel": self.textLabel, - @"imageView1": self.imageView1}]]; - - [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[imageView1]-(offset)-[detailTextLabel]-|" - options:0 - metrics:@{@"offset": @(kAlbumImageToTextSpace)} - views:@{@"detailTextLabel": self.detailTextLabel, - @"imageView1": self.imageView1}]]; - - - [self.contentView addConstraints:@[[NSLayoutConstraint constraintWithItem:self.textLabel - attribute:NSLayoutAttributeBottom - relatedBy:NSLayoutRelationEqual - toItem:self.textLabel.superview - attribute:NSLayoutAttributeCenterY - multiplier:1.f constant:0.f]]]; - [self.contentView addConstraints:@[[NSLayoutConstraint constraintWithItem:self.detailTextLabel - attribute:NSLayoutAttributeTop - relatedBy:NSLayoutRelationEqual - toItem:self.textLabel.superview - attribute:NSLayoutAttributeCenterY - multiplier:1.f constant:+4.f]]]; } - - - return self; } +-(void)layoutSubviews { + [super layoutSubviews]; + self.textLabel.frame = CGRectMake(kAlbumLeftToImageSpace + kAlbumThumbnailSize1.width + kAlbumImageToTextSpace,self.textLabel.frame.origin.y,self.contentView.frame.size.width - kAlbumLeftToImageSpace - kAlbumThumbnailSize1.width - 8, self.textLabel.frame.size.height); + self.detailTextLabel.frame = CGRectMake(kAlbumLeftToImageSpace + kAlbumThumbnailSize1.width + kAlbumImageToTextSpace,self.detailTextLabel.frame.origin.y,self.contentView.frame.size.width - kAlbumLeftToImageSpace - kAlbumThumbnailSize1.width - 8 - kAlbumImageToTextSpace, self.detailTextLabel.frame.size.height); + +} - (void)setVideoLayout:(BOOL)isVideo { // TODO : Add additional icons for slowmo, burst, etc... diff --git a/GMImagePicker/GMAlbumsViewController.m b/GMImagePicker/GMAlbumsViewController.m index f8be9b4..bb6d220 100644 --- a/GMImagePicker/GMAlbumsViewController.m +++ b/GMImagePicker/GMAlbumsViewController.m @@ -349,8 +349,8 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath -(void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section { UITableViewHeaderFooterView *header = (UITableViewHeaderFooterView *)view; - header.contentView.backgroundColor = [UIColor clearColor]; - header.backgroundView.backgroundColor = [UIColor clearColor]; +// header.contentView.backgroundColor = [UIColor clearColor]; +// header.backgroundView.backgroundColor = [UIColor clearColor]; // Default is a bold font, but keep this styled as a normal font header.textLabel.font = [UIFont fontWithName:self.picker.pickerFontName size:self.picker.pickerFontNormalSize]; From f22cd8427c02997d10c3e36b16086358f2abce6e Mon Sep 17 00:00:00 2001 From: "dinesh.kumar" Date: Mon, 18 Sep 2017 16:55:34 +0530 Subject: [PATCH 3/7] Fixed indentation with 2 spaces and removed few warnings around typecasting and proeprty synthesis. --- GMImagePicker/GMAlbumsViewCell.h | 6 +- GMImagePicker/GMAlbumsViewCell.m | 188 +++--- GMImagePicker/GMAlbumsViewController.h | 2 +- GMImagePicker/GMAlbumsViewController.m | 586 +++++++++-------- GMImagePicker/GMGridViewCell.h | 6 +- GMImagePicker/GMGridViewCell.m | 244 ++++---- GMImagePicker/GMGridViewController.h | 10 +- GMImagePicker/GMGridViewController.m | 794 ++++++++++++------------ GMImagePicker/GMImagePickerController.h | 8 +- GMImagePicker/GMImagePickerController.m | 2 +- 10 files changed, 921 insertions(+), 925 deletions(-) diff --git a/GMImagePicker/GMAlbumsViewCell.h b/GMImagePicker/GMAlbumsViewCell.h index 0394a14..31a2676 100644 --- a/GMImagePicker/GMAlbumsViewCell.h +++ b/GMImagePicker/GMAlbumsViewCell.h @@ -6,8 +6,8 @@ // Copyright (c) 2014 Guillermo Muntaner Perelló. All rights reserved. // -@import UIKit; -@import Photos; +#include +#include @interface GMAlbumsViewCell : UITableViewCell @@ -24,7 +24,7 @@ //Video additional information @property (nonatomic, strong) UIImageView *videoIcon; @property (nonatomic, strong) UIImageView *slowMoIcon; -@property (nonatomic, strong) UIView* gradientView; +@property (nonatomic, strong) UIView *gradientView; @property (nonatomic, strong) CAGradientLayer *gradient; //Selection overlay diff --git a/GMImagePicker/GMAlbumsViewCell.m b/GMImagePicker/GMAlbumsViewCell.m index fe45c6b..42a0b8d 100644 --- a/GMImagePicker/GMAlbumsViewCell.m +++ b/GMImagePicker/GMAlbumsViewCell.m @@ -15,116 +15,116 @@ @implementation GMAlbumsViewCell - (void)awakeFromNib { - [super awakeFromNib]; + [super awakeFromNib]; } - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { + + if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) + { + // self.isAccessibilityElement = YES; - if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) - { - // self.isAccessibilityElement = YES; - - self.accessoryType = UITableViewCellAccessoryDisclosureIndicator; - - // Border width of 1 pixel: - float borderWidth = 1.0/[UIScreen mainScreen].scale; - - // ImageView - _imageView3 = [UIImageView new]; - _imageView3.contentMode = UIViewContentModeScaleAspectFill; - _imageView3.frame = CGRectMake(kAlbumLeftToImageSpace+4, 8, kAlbumThumbnailSize3.width, kAlbumThumbnailSize3.height ); - [_imageView3.layer setBorderColor: [[UIColor whiteColor] CGColor]]; - [_imageView3.layer setBorderWidth: borderWidth]; - _imageView3.clipsToBounds = YES; - _imageView3.translatesAutoresizingMaskIntoConstraints = YES; - _imageView3.autoresizingMask = UIViewAutoresizingFlexibleRightMargin; - [self.contentView addSubview:_imageView3]; - - // ImageView - _imageView2 = [UIImageView new]; - _imageView2.contentMode = UIViewContentModeScaleAspectFill; - _imageView2.frame = CGRectMake(kAlbumLeftToImageSpace+2, 8+2, kAlbumThumbnailSize2.width, kAlbumThumbnailSize2.height ); - [_imageView2.layer setBorderColor: [[UIColor whiteColor] CGColor]]; - [_imageView2.layer setBorderWidth: borderWidth]; - _imageView2.clipsToBounds = YES; - _imageView2.translatesAutoresizingMaskIntoConstraints = YES; - _imageView2.autoresizingMask = UIViewAutoresizingFlexibleRightMargin; - [self.contentView addSubview:_imageView2]; - - // ImageView - _imageView1 = [UIImageView new]; - _imageView1.contentMode = UIViewContentModeScaleAspectFill; - _imageView1.frame = CGRectMake(kAlbumLeftToImageSpace, 8+4, kAlbumThumbnailSize1.width, kAlbumThumbnailSize1.height ); - [_imageView1.layer setBorderColor: [[UIColor whiteColor] CGColor]]; - [_imageView1.layer setBorderWidth: borderWidth]; - _imageView1.clipsToBounds = YES; - _imageView1.translatesAutoresizingMaskIntoConstraints = YES; - _imageView1.autoresizingMask = UIViewAutoresizingFlexibleRightMargin; - [self.contentView addSubview:_imageView1]; - - - // The video gradient, label & icon - UIColor *topGradient = [UIColor colorWithRed:0.00 green:0.00 blue:0.00 alpha:0.0]; - UIColor *midGradient = [UIColor colorWithRed:0.00 green:0.00 blue:0.00 alpha:0.33]; - UIColor *botGradient = [UIColor colorWithRed:0.00 green:0.00 blue:0.00 alpha:0.75]; - _gradientView = [[UIView alloc] initWithFrame: CGRectMake(0.0f, kAlbumThumbnailSize1.height-kAlbumGradientHeight, kAlbumThumbnailSize1.width, kAlbumGradientHeight)]; - _gradient = [CAGradientLayer layer]; - _gradient.frame = _gradientView.bounds; - _gradient.colors = [NSArray arrayWithObjects:(id)[topGradient CGColor], (id)[midGradient CGColor], (id)[botGradient CGColor], nil]; - _gradient.locations = @[ @0.0f, @0.5f, @1.0f ]; - [_gradientView.layer insertSublayer:_gradient atIndex:0]; - _gradientView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin; - _gradientView.translatesAutoresizingMaskIntoConstraints = YES; - [self.imageView1 addSubview:_gradientView]; - _gradientView.hidden = YES; - - // VideoIcon - _videoIcon = [UIImageView new]; - _videoIcon.contentMode = UIViewContentModeScaleAspectFill; - _videoIcon.frame = CGRectMake(3,kAlbumThumbnailSize1.height - 4 - 8, 15, 8 ); - _videoIcon.image = [UIImage imageNamed:@"GMVideoIcon" inBundle:[NSBundle bundleForClass:GMAlbumsViewCell.class] compatibleWithTraitCollection:nil]; - _videoIcon.clipsToBounds = YES; - _videoIcon.translatesAutoresizingMaskIntoConstraints = YES; - _videoIcon.autoresizingMask = UIViewAutoresizingFlexibleRightMargin; - [self.imageView1 addSubview:_videoIcon]; - _videoIcon.hidden = NO; - - // TextLabel - self.textLabel.font = [UIFont fontWithName:@"HelveticaNeue" size:17.0]; - self.textLabel.numberOfLines = 1; - - self.detailTextLabel.font = [UIFont fontWithName:@"HelveticaNeue" size:14.0]; - self.detailTextLabel.numberOfLines = 1; - - } - return self; + self.accessoryType = UITableViewCellAccessoryDisclosureIndicator; + + // Border width of 1 pixel: + float borderWidth = 1.0/[UIScreen mainScreen].scale; + + // ImageView + _imageView3 = [UIImageView new]; + _imageView3.contentMode = UIViewContentModeScaleAspectFill; + _imageView3.frame = CGRectMake(kAlbumLeftToImageSpace+4, 8, kAlbumThumbnailSize3.width, kAlbumThumbnailSize3.height ); + [_imageView3.layer setBorderColor: [[UIColor whiteColor] CGColor]]; + [_imageView3.layer setBorderWidth: borderWidth]; + _imageView3.clipsToBounds = YES; + _imageView3.translatesAutoresizingMaskIntoConstraints = YES; + _imageView3.autoresizingMask = UIViewAutoresizingFlexibleRightMargin; + [self.contentView addSubview:_imageView3]; + + // ImageView + _imageView2 = [UIImageView new]; + _imageView2.contentMode = UIViewContentModeScaleAspectFill; + _imageView2.frame = CGRectMake(kAlbumLeftToImageSpace+2, 8+2, kAlbumThumbnailSize2.width, kAlbumThumbnailSize2.height ); + [_imageView2.layer setBorderColor: [[UIColor whiteColor] CGColor]]; + [_imageView2.layer setBorderWidth: borderWidth]; + _imageView2.clipsToBounds = YES; + _imageView2.translatesAutoresizingMaskIntoConstraints = YES; + _imageView2.autoresizingMask = UIViewAutoresizingFlexibleRightMargin; + [self.contentView addSubview:_imageView2]; + + // ImageView + _imageView1 = [UIImageView new]; + _imageView1.contentMode = UIViewContentModeScaleAspectFill; + _imageView1.frame = CGRectMake(kAlbumLeftToImageSpace, 8+4, kAlbumThumbnailSize1.width, kAlbumThumbnailSize1.height ); + [_imageView1.layer setBorderColor: [[UIColor whiteColor] CGColor]]; + [_imageView1.layer setBorderWidth: borderWidth]; + _imageView1.clipsToBounds = YES; + _imageView1.translatesAutoresizingMaskIntoConstraints = YES; + _imageView1.autoresizingMask = UIViewAutoresizingFlexibleRightMargin; + [self.contentView addSubview:_imageView1]; + + + // The video gradient, label & icon + UIColor *topGradient = [UIColor colorWithRed:0.00 green:0.00 blue:0.00 alpha:0.0]; + UIColor *midGradient = [UIColor colorWithRed:0.00 green:0.00 blue:0.00 alpha:0.33]; + UIColor *botGradient = [UIColor colorWithRed:0.00 green:0.00 blue:0.00 alpha:0.75]; + _gradientView = [[UIView alloc] initWithFrame: CGRectMake(0.0f, kAlbumThumbnailSize1.height-kAlbumGradientHeight, kAlbumThumbnailSize1.width, kAlbumGradientHeight)]; + _gradient = [CAGradientLayer layer]; + _gradient.frame = _gradientView.bounds; + _gradient.colors = [NSArray arrayWithObjects:(id)[topGradient CGColor], (id)[midGradient CGColor], (id)[botGradient CGColor], nil]; + _gradient.locations = @[ @0.0f, @0.5f, @1.0f ]; + [_gradientView.layer insertSublayer:_gradient atIndex:0]; + _gradientView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin; + _gradientView.translatesAutoresizingMaskIntoConstraints = YES; + [self.imageView1 addSubview:_gradientView]; + _gradientView.hidden = YES; + + // VideoIcon + _videoIcon = [UIImageView new]; + _videoIcon.contentMode = UIViewContentModeScaleAspectFill; + _videoIcon.frame = CGRectMake(3,kAlbumThumbnailSize1.height - 4 - 8, 15, 8 ); + _videoIcon.image = [UIImage imageNamed:@"GMVideoIcon" inBundle:[NSBundle bundleForClass:GMAlbumsViewCell.class] compatibleWithTraitCollection:nil]; + _videoIcon.clipsToBounds = YES; + _videoIcon.translatesAutoresizingMaskIntoConstraints = YES; + _videoIcon.autoresizingMask = UIViewAutoresizingFlexibleRightMargin; + [self.imageView1 addSubview:_videoIcon]; + _videoIcon.hidden = NO; + + // TextLabel + self.textLabel.font = [UIFont fontWithName:@"HelveticaNeue" size:17.0]; + self.textLabel.numberOfLines = 1; + + self.detailTextLabel.font = [UIFont fontWithName:@"HelveticaNeue" size:14.0]; + self.detailTextLabel.numberOfLines = 1; + + } + return self; } -(void)layoutSubviews { - [super layoutSubviews]; - self.textLabel.frame = CGRectMake(kAlbumLeftToImageSpace + kAlbumThumbnailSize1.width + kAlbumImageToTextSpace,self.textLabel.frame.origin.y,self.contentView.frame.size.width - kAlbumLeftToImageSpace - kAlbumThumbnailSize1.width - 8, self.textLabel.frame.size.height); - self.detailTextLabel.frame = CGRectMake(kAlbumLeftToImageSpace + kAlbumThumbnailSize1.width + kAlbumImageToTextSpace,self.detailTextLabel.frame.origin.y,self.contentView.frame.size.width - kAlbumLeftToImageSpace - kAlbumThumbnailSize1.width - 8 - kAlbumImageToTextSpace, self.detailTextLabel.frame.size.height); - + [super layoutSubviews]; + self.textLabel.frame = CGRectMake(kAlbumLeftToImageSpace + kAlbumThumbnailSize1.width + kAlbumImageToTextSpace,self.textLabel.frame.origin.y,self.contentView.frame.size.width - kAlbumLeftToImageSpace - kAlbumThumbnailSize1.width - 8, self.textLabel.frame.size.height); + self.detailTextLabel.frame = CGRectMake(kAlbumLeftToImageSpace + kAlbumThumbnailSize1.width + kAlbumImageToTextSpace,self.detailTextLabel.frame.origin.y,self.contentView.frame.size.width - kAlbumLeftToImageSpace - kAlbumThumbnailSize1.width - 8 - kAlbumImageToTextSpace, self.detailTextLabel.frame.size.height); + } - (void)setVideoLayout:(BOOL)isVideo { - // TODO : Add additional icons for slowmo, burst, etc... - if (isVideo) { - _videoIcon.hidden = NO; - _gradientView.hidden = NO; - } else { - _videoIcon.hidden = YES; - _gradientView.hidden = YES; - } + // TODO : Add additional icons for slowmo, burst, etc... + if (isVideo) { + _videoIcon.hidden = NO; + _gradientView.hidden = NO; + } else { + _videoIcon.hidden = YES; + _gradientView.hidden = YES; + } } - (void)setSelected:(BOOL)selected animated:(BOOL)animated { - [super setSelected:selected animated:animated]; - - // Configure the view for the selected state + [super setSelected:selected animated:animated]; + + // Configure the view for the selected state } @end diff --git a/GMImagePicker/GMAlbumsViewController.h b/GMImagePicker/GMAlbumsViewController.h index cffc9ca..d60dc28 100644 --- a/GMImagePicker/GMAlbumsViewController.h +++ b/GMImagePicker/GMAlbumsViewController.h @@ -29,4 +29,4 @@ static CGSize const kAlbumThumbnailSize3 = {62.0f , 62.0f}; - (void)selectAllAlbumsCell; -@end \ No newline at end of file +@end diff --git a/GMImagePicker/GMAlbumsViewController.m b/GMImagePicker/GMAlbumsViewController.m index bb6d220..edabc33 100644 --- a/GMImagePicker/GMAlbumsViewController.m +++ b/GMImagePicker/GMAlbumsViewController.m @@ -12,16 +12,16 @@ #import "GMGridViewController.h" #import "GMAlbumsViewCell.h" -@import Photos; +#include @interface GMAlbumsViewController() -@property (strong) NSArray *collectionsFetchResults; -@property (strong) NSArray *collectionsLocalizedTitles; -@property (strong) NSArray *collectionsFetchResultsAssets; -@property (strong) NSArray *collectionsFetchResultsTitles; +@property (strong,nonatomic) NSArray *collectionsFetchResults; +@property (strong,nonatomic) NSArray *collectionsLocalizedTitles; +@property (strong,nonatomic) NSArray *collectionsFetchResultsAssets; +@property (strong,nonatomic) NSArray *collectionsFetchResultsTitles; @property (nonatomic, weak) GMImagePickerController *picker; -@property (strong) PHCachingImageManager *imageManager; +@property (strong,nonatomic) PHCachingImageManager *imageManager; @end @@ -30,174 +30,174 @@ @implementation GMAlbumsViewController - (id)init { - if (self = [super initWithStyle:UITableViewStylePlain]) { - self.preferredContentSize = kPopoverContentSize; - } - - return self; + if (self = [super initWithStyle:UITableViewStylePlain]) { + self.preferredContentSize = kPopoverContentSize; + } + + return self; } -static NSString * const AllPhotosReuseIdentifier = @"AllPhotosCell"; -static NSString * const CollectionCellReuseIdentifier = @"CollectionCell"; +static NSString *const AllPhotosReuseIdentifier = @"AllPhotosCell"; +static NSString *const CollectionCellReuseIdentifier = @"CollectionCell"; - (void)viewDidLoad { - [super viewDidLoad]; - - self.view.backgroundColor = [self.picker pickerBackgroundColor]; - - // Navigation bar customization - if (self.picker.customNavigationBarPrompt) { - self.navigationItem.prompt = self.picker.customNavigationBarPrompt; - } - - self.imageManager = [[PHCachingImageManager alloc] init]; - - // Table view aspect - self.tableView.rowHeight = kAlbumRowHeight; - self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone; - - // Buttons - NSDictionary* barButtonItemAttributes = @{NSFontAttributeName: [UIFont fontWithName:self.picker.pickerFontName size:self.picker.pickerFontHeaderSize]}; - - NSString *cancelTitle = self.picker.customCancelButtonTitle ? self.picker.customCancelButtonTitle : NSLocalizedStringFromTableInBundle(@"picker.navigation.cancel-button", @"GMImagePicker", [NSBundle bundleForClass:GMImagePickerController.class], @"Cancel"); - self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:cancelTitle - style:UIBarButtonItemStylePlain - target:self.picker - action:@selector(dismiss:)]; + [super viewDidLoad]; + + self.view.backgroundColor = [self.picker pickerBackgroundColor]; + + // Navigation bar customization + if (self.picker.customNavigationBarPrompt) { + self.navigationItem.prompt = self.picker.customNavigationBarPrompt; + } + + self.imageManager = [[PHCachingImageManager alloc] init]; + + // Table view aspect + self.tableView.rowHeight = kAlbumRowHeight; + self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone; + + // Buttons + NSDictionary *barButtonItemAttributes = @{NSFontAttributeName: [UIFont fontWithName:self.picker.pickerFontName size:self.picker.pickerFontHeaderSize]}; + + NSString *cancelTitle = self.picker.customCancelButtonTitle ? self.picker.customCancelButtonTitle : NSLocalizedStringFromTableInBundle(@"picker.navigation.cancel-button", @"GMImagePicker", [NSBundle bundleForClass:GMImagePickerController.class], @"Cancel"); + self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:cancelTitle + style:UIBarButtonItemStylePlain + target:self.picker + action:@selector(dismiss:)]; + if (self.picker.useCustomFontForNavigationBar) { + [self.navigationItem.leftBarButtonItem setTitleTextAttributes:barButtonItemAttributes forState:UIControlStateNormal]; + [self.navigationItem.leftBarButtonItem setTitleTextAttributes:barButtonItemAttributes forState:UIControlStateSelected]; + } + + if (self.picker.allowsMultipleSelection) { + NSString *doneTitle = self.picker.customDoneButtonTitle ? self.picker.customDoneButtonTitle : NSLocalizedStringFromTableInBundle(@"picker.navigation.done-button", @"GMImagePicker", [NSBundle bundleForClass:GMImagePickerController.class], @"Done"); + self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:doneTitle + style:UIBarButtonItemStyleDone + target:self.picker + action:@selector(finishPickingAssets:)]; if (self.picker.useCustomFontForNavigationBar) { - [self.navigationItem.leftBarButtonItem setTitleTextAttributes:barButtonItemAttributes forState:UIControlStateNormal]; - [self.navigationItem.leftBarButtonItem setTitleTextAttributes:barButtonItemAttributes forState:UIControlStateSelected]; - } - - if (self.picker.allowsMultipleSelection) { - NSString *doneTitle = self.picker.customDoneButtonTitle ? self.picker.customDoneButtonTitle : NSLocalizedStringFromTableInBundle(@"picker.navigation.done-button", @"GMImagePicker", [NSBundle bundleForClass:GMImagePickerController.class], @"Done"); - self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:doneTitle - style:UIBarButtonItemStyleDone - target:self.picker - action:@selector(finishPickingAssets:)]; - if (self.picker.useCustomFontForNavigationBar) { - [self.navigationItem.rightBarButtonItem setTitleTextAttributes:barButtonItemAttributes forState:UIControlStateNormal]; - [self.navigationItem.rightBarButtonItem setTitleTextAttributes:barButtonItemAttributes forState:UIControlStateSelected]; - } - - self.navigationItem.rightBarButtonItem.enabled = (self.picker.autoDisableDoneButton ? self.picker.selectedAssets.count > 0 : TRUE); + [self.navigationItem.rightBarButtonItem setTitleTextAttributes:barButtonItemAttributes forState:UIControlStateNormal]; + [self.navigationItem.rightBarButtonItem setTitleTextAttributes:barButtonItemAttributes forState:UIControlStateSelected]; } - // Bottom toolbar - self.toolbarItems = self.picker.toolbarItems; - - // Title - if (!self.picker.title) { - self.title = NSLocalizedStringFromTableInBundle(@"picker.navigation.title", @"GMImagePicker", [NSBundle bundleForClass:GMImagePickerController.class], @"Navigation bar default title"); - } else { - self.title = self.picker.title; - } - - // Fetch PHAssetCollections: - PHFetchResult *topLevelUserCollections = [PHCollectionList fetchTopLevelUserCollectionsWithOptions:nil]; - PHFetchResult *smartAlbums = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil]; - self.collectionsFetchResults = @[topLevelUserCollections, smartAlbums]; - self.collectionsLocalizedTitles = @[NSLocalizedStringFromTableInBundle(@"picker.table.user-albums-header", @"GMImagePicker", [NSBundle bundleForClass:GMImagePickerController.class], @"Albums"), NSLocalizedStringFromTableInBundle(@"picker.table.smart-albums-header", @"GMImagePicker", [NSBundle bundleForClass:GMImagePickerController.class], @"Smart Albums")]; - - [self updateFetchResults]; - - // Register for changes - [[PHPhotoLibrary sharedPhotoLibrary] registerChangeObserver:self]; - - if ([self respondsToSelector:@selector(setEdgesForExtendedLayout:)]) - { - self.edgesForExtendedLayout = UIRectEdgeNone; - } + self.navigationItem.rightBarButtonItem.enabled = (self.picker.autoDisableDoneButton ? self.picker.selectedAssets.count > 0 : TRUE); + } + + // Bottom toolbar + self.toolbarItems = self.picker.toolbarItems; + + // Title + if (!self.picker.title) { + self.title = NSLocalizedStringFromTableInBundle(@"picker.navigation.title", @"GMImagePicker", [NSBundle bundleForClass:GMImagePickerController.class], @"Navigation bar default title"); + } else { + self.title = self.picker.title; + } + + // Fetch PHAssetCollections: + PHFetchResult *topLevelUserCollections = [PHCollectionList fetchTopLevelUserCollectionsWithOptions:nil]; + PHFetchResult *smartAlbums = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeSmartAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil]; + self.collectionsFetchResults = @[topLevelUserCollections, smartAlbums]; + self.collectionsLocalizedTitles = @[NSLocalizedStringFromTableInBundle(@"picker.table.user-albums-header", @"GMImagePicker", [NSBundle bundleForClass:GMImagePickerController.class], @"Albums"), NSLocalizedStringFromTableInBundle(@"picker.table.smart-albums-header", @"GMImagePicker", [NSBundle bundleForClass:GMImagePickerController.class], @"Smart Albums")]; + + [self updateFetchResults]; + + // Register for changes + [[PHPhotoLibrary sharedPhotoLibrary] registerChangeObserver:self]; + + if ([self respondsToSelector:@selector(setEdgesForExtendedLayout:)]) + { + self.edgesForExtendedLayout = UIRectEdgeNone; + } } - (void)dealloc { - [[PHPhotoLibrary sharedPhotoLibrary] unregisterChangeObserver:self]; + [[PHPhotoLibrary sharedPhotoLibrary] unregisterChangeObserver:self]; } - (UIStatusBarStyle)preferredStatusBarStyle { - return self.picker.pickerStatusBarStyle; + return self.picker.pickerStatusBarStyle; } - (void)selectAllAlbumsCell { - NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0]; - [self tableView:self.tableView didSelectRowAtIndexPath:indexPath]; + NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:0]; + [self tableView:self.tableView didSelectRowAtIndexPath:indexPath]; } -(void)updateFetchResults { - //What I do here is fetch both the albums list and the assets of each album. - //This way I have acces to the number of items in each album, I can load the 3 - //thumbnails directly and I can pass the fetched result to the gridViewController. - - self.collectionsFetchResultsAssets=nil; - self.collectionsFetchResultsTitles=nil; - - //Fetch PHAssetCollections: - PHFetchResult *topLevelUserCollections = [self.collectionsFetchResults objectAtIndex:0]; - PHFetchResult *smartAlbums = [self.collectionsFetchResults objectAtIndex:1]; - - //All album: Sorted by descending creation date. - NSMutableArray *allFetchResultArray = [[NSMutableArray alloc] init]; - NSMutableArray *allFetchResultLabel = [[NSMutableArray alloc] init]; + //What I do here is fetch both the albums list and the assets of each album. + //This way I have acces to the number of items in each album, I can load the 3 + //thumbnails directly and I can pass the fetched result to the gridViewController. + + self.collectionsFetchResultsAssets=nil; + self.collectionsFetchResultsTitles=nil; + + //Fetch PHAssetCollections: + PHFetchResult *topLevelUserCollections = [self.collectionsFetchResults objectAtIndex:0]; + PHFetchResult *smartAlbums = [self.collectionsFetchResults objectAtIndex:1]; + + //All album: Sorted by descending creation date. + NSMutableArray *allFetchResultArray = [[NSMutableArray alloc] init]; + NSMutableArray *allFetchResultLabel = [[NSMutableArray alloc] init]; + { + PHFetchOptions *options = [[PHFetchOptions alloc] init]; + options.predicate = [NSPredicate predicateWithFormat:@"mediaType in %@", self.picker.mediaTypes]; + options.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:NO]]; + PHFetchResult *assetsFetchResult = [PHAsset fetchAssetsWithOptions:options]; + [allFetchResultArray addObject:assetsFetchResult]; + [allFetchResultLabel addObject:NSLocalizedStringFromTableInBundle(@"picker.table.all-photos-label", @"GMImagePicker", [NSBundle bundleForClass:GMImagePickerController.class], @"All photos")]; + } + + //User albums: + NSMutableArray *userFetchResultArray = [[NSMutableArray alloc] init]; + NSMutableArray *userFetchResultLabel = [[NSMutableArray alloc] init]; + for(PHCollection *collection in topLevelUserCollections) + { + if ([collection isKindOfClass:[PHAssetCollection class]]) + { + PHFetchOptions *options = [[PHFetchOptions alloc] init]; + options.predicate = [NSPredicate predicateWithFormat:@"mediaType in %@", self.picker.mediaTypes]; + PHAssetCollection *assetCollection = (PHAssetCollection *)collection; + + //Albums collections are allways PHAssetCollectionType=1 & PHAssetCollectionSubtype=2 + + PHFetchResult *assetsFetchResult = [PHAsset fetchAssetsInAssetCollection:assetCollection options:options]; + [userFetchResultArray addObject:assetsFetchResult]; + [userFetchResultLabel addObject:collection.localizedTitle]; + } + } + + + //Smart albums: Sorted by descending creation date. + NSMutableArray *smartFetchResultArray = [[NSMutableArray alloc] init]; + NSMutableArray *smartFetchResultLabel = [[NSMutableArray alloc] init]; + for(PHCollection *collection in smartAlbums) + { + if ([collection isKindOfClass:[PHAssetCollection class]]) { + PHAssetCollection *assetCollection = (PHAssetCollection *)collection; + + //Smart collections are PHAssetCollectionType=2; + if(self.picker.customSmartCollections && [self.picker.customSmartCollections containsObject:@(assetCollection.assetCollectionSubtype)]) + { PHFetchOptions *options = [[PHFetchOptions alloc] init]; options.predicate = [NSPredicate predicateWithFormat:@"mediaType in %@", self.picker.mediaTypes]; options.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:NO]]; - PHFetchResult *assetsFetchResult = [PHAsset fetchAssetsWithOptions:options]; - [allFetchResultArray addObject:assetsFetchResult]; - [allFetchResultLabel addObject:NSLocalizedStringFromTableInBundle(@"picker.table.all-photos-label", @"GMImagePicker", [NSBundle bundleForClass:GMImagePickerController.class], @"All photos")]; - } - - //User albums: - NSMutableArray *userFetchResultArray = [[NSMutableArray alloc] init]; - NSMutableArray *userFetchResultLabel = [[NSMutableArray alloc] init]; - for(PHCollection *collection in topLevelUserCollections) - { - if ([collection isKindOfClass:[PHAssetCollection class]]) - { - PHFetchOptions *options = [[PHFetchOptions alloc] init]; - options.predicate = [NSPredicate predicateWithFormat:@"mediaType in %@", self.picker.mediaTypes]; - PHAssetCollection *assetCollection = (PHAssetCollection *)collection; - - //Albums collections are allways PHAssetCollectionType=1 & PHAssetCollectionSubtype=2 - - PHFetchResult *assetsFetchResult = [PHAsset fetchAssetsInAssetCollection:assetCollection options:options]; - [userFetchResultArray addObject:assetsFetchResult]; - [userFetchResultLabel addObject:collection.localizedTitle]; - } - } - - - //Smart albums: Sorted by descending creation date. - NSMutableArray *smartFetchResultArray = [[NSMutableArray alloc] init]; - NSMutableArray *smartFetchResultLabel = [[NSMutableArray alloc] init]; - for(PHCollection *collection in smartAlbums) - { - if ([collection isKindOfClass:[PHAssetCollection class]]) + + PHFetchResult *assetsFetchResult = [PHAsset fetchAssetsInAssetCollection:assetCollection options:options]; + if(assetsFetchResult.count>0) { - PHAssetCollection *assetCollection = (PHAssetCollection *)collection; - - //Smart collections are PHAssetCollectionType=2; - if(self.picker.customSmartCollections && [self.picker.customSmartCollections containsObject:@(assetCollection.assetCollectionSubtype)]) - { - PHFetchOptions *options = [[PHFetchOptions alloc] init]; - options.predicate = [NSPredicate predicateWithFormat:@"mediaType in %@", self.picker.mediaTypes]; - options.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:NO]]; - - PHFetchResult *assetsFetchResult = [PHAsset fetchAssetsInAssetCollection:assetCollection options:options]; - if(assetsFetchResult.count>0) - { - [smartFetchResultArray addObject:assetsFetchResult]; - [smartFetchResultLabel addObject:collection.localizedTitle]; - } - } + [smartFetchResultArray addObject:assetsFetchResult]; + [smartFetchResultLabel addObject:collection.localizedTitle]; } + } } - - self.collectionsFetchResultsAssets= @[allFetchResultArray,userFetchResultArray,smartFetchResultArray]; - self.collectionsFetchResultsTitles= @[allFetchResultLabel,userFetchResultLabel,smartFetchResultLabel]; + } + + self.collectionsFetchResultsAssets= @[allFetchResultArray,userFetchResultArray,smartFetchResultArray]; + self.collectionsFetchResultsTitles= @[allFetchResultLabel,userFetchResultLabel,smartFetchResultLabel]; } @@ -205,7 +205,7 @@ -(void)updateFetchResults - (GMImagePickerController *)picker { - return (GMImagePickerController *)self.navigationController.parentViewController; + return (GMImagePickerController *)self.navigationController.parentViewController; } @@ -213,12 +213,12 @@ - (GMImagePickerController *)picker - (BOOL)shouldAutorotate { - return YES; + return YES; } - (UIInterfaceOrientationMask)supportedInterfaceOrientations { - return UIInterfaceOrientationMaskAllButUpsideDown; + return UIInterfaceOrientationMaskAllButUpsideDown; } @@ -226,150 +226,150 @@ - (UIInterfaceOrientationMask)supportedInterfaceOrientations - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { - return self.collectionsFetchResultsAssets.count; + return (NSInteger)self.collectionsFetchResultsAssets.count; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - PHFetchResult *fetchResult = self.collectionsFetchResultsAssets[section]; - return fetchResult.count; + PHFetchResult *fetchResult = self.collectionsFetchResultsAssets[(NSUInteger)section]; + return (NSInteger)fetchResult.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { - static NSString *CellIdentifier = @"Cell"; + static NSString *CellIdentifier = @"Cell"; + + GMAlbumsViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; + if (cell == nil) { + cell = [[GMAlbumsViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier]; + cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; + } + + // Increment the cell's tag + NSInteger currentTag = cell.tag + 1; + cell.tag = currentTag; + + // Set the label + cell.textLabel.font = [UIFont fontWithName:self.picker.pickerFontName size:self.picker.pickerFontHeaderSize]; + cell.textLabel.text = (self.collectionsFetchResultsTitles[(NSUInteger)indexPath.section])[(NSUInteger)indexPath.row]; + cell.textLabel.textColor = self.picker.pickerTextColor; + + // Retrieve the pre-fetched assets for this album: + PHFetchResult *assetsFetchResult = (self.collectionsFetchResultsAssets[(NSUInteger)indexPath.section])[(NSUInteger)indexPath.row]; + + // Display the number of assets + if (self.picker.displayAlbumsNumberOfAssets) { + cell.detailTextLabel.font = [UIFont fontWithName:self.picker.pickerFontName size:self.picker.pickerFontNormalSize]; + cell.detailTextLabel.text = [self tableCellSubtitle:assetsFetchResult]; + cell.detailTextLabel.textColor = self.picker.pickerTextColor; + } + + // Set the 3 images (if exists): + if ([assetsFetchResult count] > 0) { + CGFloat scale = [UIScreen mainScreen].scale; - GMAlbumsViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; - if (cell == nil) { - cell = [[GMAlbumsViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier]; - cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; - } - - // Increment the cell's tag - NSInteger currentTag = cell.tag + 1; - cell.tag = currentTag; - - // Set the label - cell.textLabel.font = [UIFont fontWithName:self.picker.pickerFontName size:self.picker.pickerFontHeaderSize]; - cell.textLabel.text = (self.collectionsFetchResultsTitles[indexPath.section])[indexPath.row]; - cell.textLabel.textColor = self.picker.pickerTextColor; - - // Retrieve the pre-fetched assets for this album: - PHFetchResult *assetsFetchResult = (self.collectionsFetchResultsAssets[indexPath.section])[indexPath.row]; + //Compute the thumbnail pixel size: + CGSize tableCellThumbnailSize1 = CGSizeMake(kAlbumThumbnailSize1.width*scale, kAlbumThumbnailSize1.height*scale); + PHAsset *asset = assetsFetchResult[0]; + [cell setVideoLayout:(asset.mediaType==PHAssetMediaTypeVideo)]; + [self.imageManager requestImageForAsset:asset + targetSize:tableCellThumbnailSize1 + contentMode:PHImageContentModeAspectFill + options:nil + resultHandler:^(UIImage *result, NSDictionary *info) { + if (cell.tag == currentTag) { + cell.imageView1.image = result; + } + }]; - // Display the number of assets - if (self.picker.displayAlbumsNumberOfAssets) { - cell.detailTextLabel.font = [UIFont fontWithName:self.picker.pickerFontName size:self.picker.pickerFontNormalSize]; - cell.detailTextLabel.text = [self tableCellSubtitle:assetsFetchResult]; - cell.detailTextLabel.textColor = self.picker.pickerTextColor; + // Second & third images: + // TODO: Only preload the 3pixels height visible frame! + if ([assetsFetchResult count] > 1) { + //Compute the thumbnail pixel size: + CGSize tableCellThumbnailSize2 = CGSizeMake(kAlbumThumbnailSize2.width*scale, kAlbumThumbnailSize2.height*scale); + PHAsset *asset = assetsFetchResult[1]; + [self.imageManager requestImageForAsset:asset + targetSize:tableCellThumbnailSize2 + contentMode:PHImageContentModeAspectFill + options:nil + resultHandler:^(UIImage *result, NSDictionary *info) { + if (cell.tag == currentTag) { + cell.imageView2.image = result; + } + }]; + } else { + cell.imageView2.image = nil; } - // Set the 3 images (if exists): - if ([assetsFetchResult count] > 0) { - CGFloat scale = [UIScreen mainScreen].scale; - - //Compute the thumbnail pixel size: - CGSize tableCellThumbnailSize1 = CGSizeMake(kAlbumThumbnailSize1.width*scale, kAlbumThumbnailSize1.height*scale); - PHAsset *asset = assetsFetchResult[0]; - [cell setVideoLayout:(asset.mediaType==PHAssetMediaTypeVideo)]; - [self.imageManager requestImageForAsset:asset - targetSize:tableCellThumbnailSize1 - contentMode:PHImageContentModeAspectFill - options:nil - resultHandler:^(UIImage *result, NSDictionary *info) { - if (cell.tag == currentTag) { - cell.imageView1.image = result; - } - }]; - - // Second & third images: - // TODO: Only preload the 3pixels height visible frame! - if ([assetsFetchResult count] > 1) { - //Compute the thumbnail pixel size: - CGSize tableCellThumbnailSize2 = CGSizeMake(kAlbumThumbnailSize2.width*scale, kAlbumThumbnailSize2.height*scale); - PHAsset *asset = assetsFetchResult[1]; - [self.imageManager requestImageForAsset:asset - targetSize:tableCellThumbnailSize2 - contentMode:PHImageContentModeAspectFill - options:nil - resultHandler:^(UIImage *result, NSDictionary *info) { - if (cell.tag == currentTag) { - cell.imageView2.image = result; - } - }]; - } else { - cell.imageView2.image = nil; - } - - if ([assetsFetchResult count] > 2) { - CGSize tableCellThumbnailSize3 = CGSizeMake(kAlbumThumbnailSize3.width*scale, kAlbumThumbnailSize3.height*scale); - PHAsset *asset = assetsFetchResult[2]; - [self.imageManager requestImageForAsset:asset - targetSize:tableCellThumbnailSize3 - contentMode:PHImageContentModeAspectFill - options:nil - resultHandler:^(UIImage *result, NSDictionary *info) { - if (cell.tag == currentTag) { - cell.imageView3.image = result; - } - }]; - } else { - cell.imageView3.image = nil; - } + if ([assetsFetchResult count] > 2) { + CGSize tableCellThumbnailSize3 = CGSizeMake(kAlbumThumbnailSize3.width*scale, kAlbumThumbnailSize3.height*scale); + PHAsset *asset = assetsFetchResult[2]; + [self.imageManager requestImageForAsset:asset + targetSize:tableCellThumbnailSize3 + contentMode:PHImageContentModeAspectFill + options:nil + resultHandler:^(UIImage *result, NSDictionary *info) { + if (cell.tag == currentTag) { + cell.imageView3.image = result; + } + }]; } else { - [cell setVideoLayout:NO]; - cell.imageView3.image = [UIImage imageNamed:@"GMEmptyFolder"]; - cell.imageView2.image = [UIImage imageNamed:@"GMEmptyFolder"]; - cell.imageView1.image = [UIImage imageNamed:@"GMEmptyFolder"]; + cell.imageView3.image = nil; } - - return cell; + } else { + [cell setVideoLayout:NO]; + cell.imageView3.image = [UIImage imageNamed:@"GMEmptyFolder"]; + cell.imageView2.image = [UIImage imageNamed:@"GMEmptyFolder"]; + cell.imageView1.image = [UIImage imageNamed:@"GMEmptyFolder"]; + } + + return cell; } #pragma mark - UITableViewDelegate - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath]; - - // Init the GMGridViewController - GMGridViewController *gridViewController = [[GMGridViewController alloc] initWithPicker:[self picker]]; - // Set the title - gridViewController.title = cell.textLabel.text; - // Use the prefetched assets! - gridViewController.assetsFetchResults = [[_collectionsFetchResultsAssets objectAtIndex:indexPath.section] objectAtIndex:indexPath.row]; - - // Remove selection so it looks better on slide in - [tableView deselectRowAtIndexPath:indexPath animated:true]; - - // Push GMGridViewController - [self.navigationController pushViewController:gridViewController animated:YES]; + UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath]; + + // Init the GMGridViewController + GMGridViewController *gridViewController = [[GMGridViewController alloc] initWithPicker:[self picker]]; + // Set the title + gridViewController.title = cell.textLabel.text; + // Use the prefetched assets! + gridViewController.assetsFetchResults = [[_collectionsFetchResultsAssets objectAtIndex:(NSUInteger)indexPath.section] objectAtIndex:(NSUInteger)indexPath.row]; + + // Remove selection so it looks better on slide in + [tableView deselectRowAtIndexPath:indexPath animated:true]; + + // Push GMGridViewController + [self.navigationController pushViewController:gridViewController animated:YES]; } -(void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section { - UITableViewHeaderFooterView *header = (UITableViewHeaderFooterView *)view; -// header.contentView.backgroundColor = [UIColor clearColor]; -// header.backgroundView.backgroundColor = [UIColor clearColor]; - - // Default is a bold font, but keep this styled as a normal font - header.textLabel.font = [UIFont fontWithName:self.picker.pickerFontName size:self.picker.pickerFontNormalSize]; - header.textLabel.textColor = self.picker.pickerTextColor; + UITableViewHeaderFooterView *header = (UITableViewHeaderFooterView *)view; + // header.contentView.backgroundColor = [UIColor clearColor]; + // header.backgroundView.backgroundColor = [UIColor clearColor]; + + // Default is a bold font, but keep this styled as a normal font + header.textLabel.font = [UIFont fontWithName:self.picker.pickerFontName size:self.picker.pickerFontNormalSize]; + header.textLabel.textColor = self.picker.pickerTextColor; } - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { - //Tip: Returning nil hides the section header! - - NSString *title = nil; - if (section > 0) { - // Only show title for non-empty sections: - PHFetchResult *fetchResult = self.collectionsFetchResultsAssets[section]; - if (fetchResult.count > 0) { - title = self.collectionsLocalizedTitles[section - 1]; - } + //Tip: Returning nil hides the section header! + + NSString *title = nil; + if (section > 0) { + // Only show title for non-empty sections: + PHFetchResult *fetchResult = self.collectionsFetchResultsAssets[(NSUInteger)section]; + if (fetchResult.count > 0) { + title = self.collectionsLocalizedTitles[(NSUInteger)(section - 1)]; } - return title; + } + return title; } @@ -377,44 +377,40 @@ - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInte - (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(), ^{ - - NSMutableArray *updatedCollectionsFetchResults = nil; - - for (PHFetchResult *collectionsFetchResult in self.collectionsFetchResults) { - PHFetchResultChangeDetails *changeDetails = [changeInstance changeDetailsForFetchResult:collectionsFetchResult]; - if (changeDetails) { - if (!updatedCollectionsFetchResults) { - updatedCollectionsFetchResults = [self.collectionsFetchResults mutableCopy]; - } - [updatedCollectionsFetchResults replaceObjectAtIndex:[self.collectionsFetchResults indexOfObject:collectionsFetchResult] withObject:[changeDetails fetchResultAfterChanges]]; - } - } - - // This only affects to changes in albums level (add/remove/edit album) - if (updatedCollectionsFetchResults) { - self.collectionsFetchResults = updatedCollectionsFetchResults; + // Call might come on any background queue. Re-dispatch to the main queue to handle it. + dispatch_async(dispatch_get_main_queue(), ^{ + + NSMutableArray *updatedCollectionsFetchResults = nil; + + for (PHFetchResult *collectionsFetchResult in self.collectionsFetchResults) { + PHFetchResultChangeDetails *changeDetails = [changeInstance changeDetailsForFetchResult:collectionsFetchResult]; + if (changeDetails) { + if (!updatedCollectionsFetchResults) { + updatedCollectionsFetchResults = [self.collectionsFetchResults mutableCopy]; } - - // However, we want to update if photos are added, so the counts of items & thumbnails are updated too. - // Maybe some checks could be done here , but for now is OKey. - [self updateFetchResults]; - [self.tableView reloadData]; - - }); + [updatedCollectionsFetchResults replaceObjectAtIndex:[self.collectionsFetchResults indexOfObject:collectionsFetchResult] withObject:[changeDetails fetchResultAfterChanges]]; + } + } + + // This only affects to changes in albums level (add/remove/edit album) + if (updatedCollectionsFetchResults) { + self.collectionsFetchResults = updatedCollectionsFetchResults; + } + + // However, we want to update if photos are added, so the counts of items & thumbnails are updated too. + // Maybe some checks could be done here , but for now is OKey. + [self updateFetchResults]; + [self.tableView reloadData]; + + }); } - - #pragma mark - Cell Subtitle - (NSString *)tableCellSubtitle:(PHFetchResult*)assetsFetchResult { - // Just return the number of assets. Album app does this: - return [NSString stringWithFormat:@"%ld", (long)[assetsFetchResult count]]; + // Just return the number of assets. Album app does this: + return [NSString stringWithFormat:@"%ld", (long)[assetsFetchResult count]]; } - - -@end \ No newline at end of file +@end diff --git a/GMImagePicker/GMGridViewCell.h b/GMImagePicker/GMGridViewCell.h index f8d3b87..365cfdb 100644 --- a/GMImagePicker/GMGridViewCell.h +++ b/GMImagePicker/GMGridViewCell.h @@ -6,8 +6,8 @@ // Copyright (c) 2014 Guillermo Muntaner Perelló. All rights reserved. // -@import UIKit; -@import Photos; +#include +#include @interface GMGridViewCell : UICollectionViewCell @@ -29,4 +29,4 @@ - (void)bind:(PHAsset *)asset; -@end \ No newline at end of file +@end diff --git a/GMImagePicker/GMGridViewCell.m b/GMImagePicker/GMGridViewCell.m index c572090..9bbc4c0 100644 --- a/GMImagePicker/GMGridViewCell.m +++ b/GMImagePicker/GMGridViewCell.m @@ -25,152 +25,152 @@ @implementation GMGridViewCell + (void)initialize { - titleFont = [UIFont systemFontOfSize:12]; - titleHeight = 20.0f; - videoIcon = [UIImage imageNamed:@"GMImagePickerVideo"]; - titleColor = [UIColor whiteColor]; - checkedIcon = [UIImage imageNamed:@"CTAssetsPickerChecked"]; - selectedColor = [UIColor colorWithWhite:1 alpha:0.3]; - disabledColor = [UIColor colorWithWhite:1 alpha:0.9]; + titleFont = [UIFont systemFontOfSize:12]; + titleHeight = 20.0f; + videoIcon = [UIImage imageNamed:@"GMImagePickerVideo"]; + titleColor = [UIColor whiteColor]; + checkedIcon = [UIImage imageNamed:@"CTAssetsPickerChecked"]; + selectedColor = [UIColor colorWithWhite:1 alpha:0.3]; + disabledColor = [UIColor colorWithWhite:1 alpha:0.9]; } - (void)awakeFromNib { - [super awakeFromNib]; - - self.contentView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; - self.contentView.translatesAutoresizingMaskIntoConstraints = YES; + [super awakeFromNib]; + + self.contentView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; + self.contentView.translatesAutoresizingMaskIntoConstraints = YES; } - (id)initWithFrame:(CGRect)frame { - if (self = [super initWithFrame:frame]) { - self.opaque = NO; - self.enabled = YES; - - CGFloat cellSize = self.contentView.bounds.size.width; - - // The image view - _imageView = [UIImageView new]; - _imageView.frame = CGRectMake(0, 0, cellSize, cellSize); - _imageView.contentMode = UIViewContentModeScaleAspectFill; - /*if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) - { - _imageView.contentMode = UIViewContentModeScaleAspectFit; - } - else - { - _imageView.contentMode = UIViewContentModeScaleAspectFill; - }*/ - _imageView.clipsToBounds = YES; - _imageView.translatesAutoresizingMaskIntoConstraints = NO; - _imageView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; - [self addSubview:_imageView]; - - - // The video gradient, label & icon - float x_offset = 4.0f; - UIColor *topGradient = [UIColor colorWithRed:0.00 green:0.00 blue:0.00 alpha:0.0]; - UIColor *botGradient = [UIColor colorWithRed:0.00 green:0.00 blue:0.00 alpha:0.8]; - _gradientView = [[UIView alloc] initWithFrame: CGRectMake(0.0f, self.bounds.size.height-titleHeight, self.bounds.size.width, titleHeight)]; - _gradient = [CAGradientLayer layer]; - _gradient.frame = _gradientView.bounds; - _gradient.colors = [NSArray arrayWithObjects:(id)[topGradient CGColor], (id)[botGradient CGColor], nil]; - [_gradientView.layer insertSublayer:_gradient atIndex:0]; - _gradientView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin; - _gradientView.translatesAutoresizingMaskIntoConstraints = NO; - [self addSubview:_gradientView]; - _gradientView.hidden = YES; - - _videoIcon = [UIImageView new]; - _videoIcon.frame = CGRectMake(x_offset, self.bounds.size.height-titleHeight, self.bounds.size.width-2*x_offset, titleHeight); - _videoIcon.contentMode = UIViewContentModeLeft; - _videoIcon.image = [UIImage imageNamed:@"GMVideoIcon" inBundle:[NSBundle bundleForClass:GMGridViewCell.class] compatibleWithTraitCollection:nil]; - _videoIcon.translatesAutoresizingMaskIntoConstraints = NO; - _videoIcon.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleWidth; - [self addSubview:_videoIcon]; - _videoIcon.hidden = YES; - - _videoDuration = [UILabel new]; - _videoDuration.font = titleFont; - _videoDuration.textColor = titleColor; - _videoDuration.textAlignment = NSTextAlignmentRight; - _videoDuration.frame = CGRectMake(x_offset, self.bounds.size.height-titleHeight, self.bounds.size.width-2*x_offset, titleHeight); - _videoDuration.contentMode = UIViewContentModeRight; - _videoDuration.translatesAutoresizingMaskIntoConstraints = NO; - _videoDuration.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleWidth; - [self addSubview:_videoDuration]; - _videoDuration.hidden = YES; - - // Selection overlay & icon - _coverView = [[UIView alloc] initWithFrame:self.bounds]; - _coverView.translatesAutoresizingMaskIntoConstraints = NO; - _coverView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; - _coverView.backgroundColor = [UIColor colorWithRed:0.24 green:0.47 blue:0.85 alpha:0.6]; - [self addSubview:_coverView]; - _coverView.hidden = YES; - - _selectedButton = [UIButton buttonWithType:UIButtonTypeCustom]; - _selectedButton.frame = CGRectMake(2*self.bounds.size.width/3, 0*self.bounds.size.width/3, self.bounds.size.width/3, self.bounds.size.width/3); - _selectedButton.contentMode = UIViewContentModeTopRight; - _selectedButton.adjustsImageWhenHighlighted = NO; - [_selectedButton setImage:nil forState:UIControlStateNormal]; - _selectedButton.translatesAutoresizingMaskIntoConstraints = NO; - _selectedButton.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; - [_selectedButton setImage:[UIImage imageNamed:@"GMSelected" inBundle:[NSBundle bundleForClass:GMGridViewCell.class] compatibleWithTraitCollection:nil] forState:UIControlStateSelected]; - _selectedButton.hidden = NO; - _selectedButton.userInteractionEnabled = NO; - [self addSubview:_selectedButton]; - } - - // Note: the views above are created in case this is toggled per cell, on the fly, etc.! - self.shouldShowSelection = YES; - - return self; + if (self = [super initWithFrame:frame]) { + self.opaque = NO; + self.enabled = YES; + + CGFloat cellSize = self.contentView.bounds.size.width; + + // The image view + _imageView = [UIImageView new]; + _imageView.frame = CGRectMake(0, 0, cellSize, cellSize); + _imageView.contentMode = UIViewContentModeScaleAspectFill; + /*if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) + { + _imageView.contentMode = UIViewContentModeScaleAspectFit; + } + else + { + _imageView.contentMode = UIViewContentModeScaleAspectFill; + }*/ + _imageView.clipsToBounds = YES; + _imageView.translatesAutoresizingMaskIntoConstraints = NO; + _imageView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; + [self addSubview:_imageView]; + + + // The video gradient, label & icon + float x_offset = 4.0f; + UIColor *topGradient = [UIColor colorWithRed:0.00 green:0.00 blue:0.00 alpha:0.0]; + UIColor *botGradient = [UIColor colorWithRed:0.00 green:0.00 blue:0.00 alpha:0.8]; + _gradientView = [[UIView alloc] initWithFrame: CGRectMake(0.0f, self.bounds.size.height-titleHeight, self.bounds.size.width, titleHeight)]; + _gradient = [CAGradientLayer layer]; + _gradient.frame = _gradientView.bounds; + _gradient.colors = [NSArray arrayWithObjects:(id)[topGradient CGColor], (id)[botGradient CGColor], nil]; + [_gradientView.layer insertSublayer:_gradient atIndex:0]; + _gradientView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleTopMargin; + _gradientView.translatesAutoresizingMaskIntoConstraints = NO; + [self addSubview:_gradientView]; + _gradientView.hidden = YES; + + _videoIcon = [UIImageView new]; + _videoIcon.frame = CGRectMake(x_offset, self.bounds.size.height-titleHeight, self.bounds.size.width-2*x_offset, titleHeight); + _videoIcon.contentMode = UIViewContentModeLeft; + _videoIcon.image = [UIImage imageNamed:@"GMVideoIcon" inBundle:[NSBundle bundleForClass:GMGridViewCell.class] compatibleWithTraitCollection:nil]; + _videoIcon.translatesAutoresizingMaskIntoConstraints = NO; + _videoIcon.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleWidth; + [self addSubview:_videoIcon]; + _videoIcon.hidden = YES; + + _videoDuration = [UILabel new]; + _videoDuration.font = titleFont; + _videoDuration.textColor = titleColor; + _videoDuration.textAlignment = NSTextAlignmentRight; + _videoDuration.frame = CGRectMake(x_offset, self.bounds.size.height-titleHeight, self.bounds.size.width-2*x_offset, titleHeight); + _videoDuration.contentMode = UIViewContentModeRight; + _videoDuration.translatesAutoresizingMaskIntoConstraints = NO; + _videoDuration.autoresizingMask = UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleWidth; + [self addSubview:_videoDuration]; + _videoDuration.hidden = YES; + + // Selection overlay & icon + _coverView = [[UIView alloc] initWithFrame:self.bounds]; + _coverView.translatesAutoresizingMaskIntoConstraints = NO; + _coverView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; + _coverView.backgroundColor = [UIColor colorWithRed:0.24 green:0.47 blue:0.85 alpha:0.6]; + [self addSubview:_coverView]; + _coverView.hidden = YES; + + _selectedButton = [UIButton buttonWithType:UIButtonTypeCustom]; + _selectedButton.frame = CGRectMake(2*self.bounds.size.width/3, 0*self.bounds.size.width/3, self.bounds.size.width/3, self.bounds.size.width/3); + _selectedButton.contentMode = UIViewContentModeTopRight; + _selectedButton.adjustsImageWhenHighlighted = NO; + [_selectedButton setImage:nil forState:UIControlStateNormal]; + _selectedButton.translatesAutoresizingMaskIntoConstraints = NO; + _selectedButton.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; + [_selectedButton setImage:[UIImage imageNamed:@"GMSelected" inBundle:[NSBundle bundleForClass:GMGridViewCell.class] compatibleWithTraitCollection:nil] forState:UIControlStateSelected]; + _selectedButton.hidden = NO; + _selectedButton.userInteractionEnabled = NO; + [self addSubview:_selectedButton]; + } + + // Note: the views above are created in case this is toggled per cell, on the fly, etc.! + self.shouldShowSelection = YES; + + return self; } // Required to resize the CAGradientLayer because it does not support auto resizing. - (void)layoutSubviews { - [super layoutSubviews]; - _gradient.frame = _gradientView.bounds; + [super layoutSubviews]; + _gradient.frame = _gradientView.bounds; } - (void)bind:(PHAsset *)asset { - self.asset = asset; - - if (self.asset.mediaType == PHAssetMediaTypeVideo) { - _videoIcon.hidden = NO; - _videoDuration.hidden = NO; - _gradientView.hidden = NO; - _videoDuration.text = [self getDurationWithFormat:self.asset.duration]; - } else { - _videoIcon.hidden = YES; - _videoDuration.hidden = YES; - _gradientView.hidden = YES; - } + self.asset = asset; + + if (self.asset.mediaType == PHAssetMediaTypeVideo) { + _videoIcon.hidden = NO; + _videoDuration.hidden = NO; + _gradientView.hidden = NO; + _videoDuration.text = [self getDurationWithFormat:self.asset.duration]; + } else { + _videoIcon.hidden = YES; + _videoDuration.hidden = YES; + _gradientView.hidden = YES; + } } // Override setSelected - (void)setSelected:(BOOL)selected { - [super setSelected:selected]; - - if (!self.shouldShowSelection) { - return; - } - - _coverView.hidden = !selected; - _selectedButton.selected = selected; + [super setSelected:selected]; + + if (!self.shouldShowSelection) { + return; + } + + _coverView.hidden = !selected; + _selectedButton.selected = selected; } -(NSString*)getDurationWithFormat:(NSTimeInterval)duration { - NSInteger ti = (NSInteger)duration; - NSInteger seconds = ti % 60; - NSInteger minutes = (ti / 60) % 60; - //NSInteger hours = (ti / 3600); - return [NSString stringWithFormat:@"%02ld:%02ld", (long)minutes, (long)seconds]; + NSInteger ti = (NSInteger)duration; + NSInteger seconds = ti % 60; + NSInteger minutes = (ti / 60) % 60; + //NSInteger hours = (ti / 3600); + return [NSString stringWithFormat:@"%02ld:%02ld", (long)minutes, (long)seconds]; } -@end \ No newline at end of file +@end diff --git a/GMImagePicker/GMGridViewController.h b/GMImagePicker/GMGridViewController.h index f0c880e..f3941e4 100644 --- a/GMImagePicker/GMGridViewController.h +++ b/GMImagePicker/GMGridViewController.h @@ -8,14 +8,14 @@ #import "GMImagePickerController.h" -@import UIKit; -@import Photos; +#include +#include @interface GMGridViewController : UICollectionViewController -@property (strong) PHFetchResult *assetsFetchResults; +@property (strong,nonatomic) PHFetchResult *assetsFetchResults; -(id)initWithPicker:(GMImagePickerController *)picker; - -@end \ No newline at end of file + +@end diff --git a/GMImagePicker/GMGridViewController.m b/GMImagePicker/GMGridViewController.m index 3c60805..81d4896 100644 --- a/GMImagePicker/GMGridViewController.m +++ b/GMImagePicker/GMGridViewController.m @@ -11,30 +11,30 @@ #import "GMAlbumsViewController.h" #import "GMGridViewCell.h" -@import Photos; +#include //Helper methods @implementation NSIndexSet (Convenience) - (NSArray *)aapl_indexPathsFromIndexesWithSection:(NSUInteger)section { - NSMutableArray *indexPaths = [NSMutableArray arrayWithCapacity:self.count]; - [self enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) { - [indexPaths addObject:[NSIndexPath indexPathForItem:idx inSection:section]]; - }]; - return indexPaths; + NSMutableArray *indexPaths = [NSMutableArray arrayWithCapacity:self.count]; + [self enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL *stop) { + [indexPaths addObject:[NSIndexPath indexPathForItem:(NSInteger)idx inSection:(NSInteger)section]]; + }]; + return indexPaths; } @end @implementation UICollectionView (Convenience) - (NSArray *)aapl_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; + 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 @@ -53,8 +53,8 @@ - (UIView *)noAssetsView; @interface GMGridViewController () @property (nonatomic, weak) GMImagePickerController *picker; -@property (strong) PHCachingImageManager *imageManager; -@property CGRect previousPreheatRect; +@property (strong,nonatomic) PHCachingImageManager *imageManager; +@property (assign, nonatomic) CGRect previousPreheatRect; @end @@ -63,100 +63,100 @@ @interface GMGridViewController () @implementation GMGridViewController { - CGFloat screenWidth; - CGFloat screenHeight; - UICollectionViewFlowLayout *portraitLayout; - UICollectionViewFlowLayout *landscapeLayout; + CGFloat screenWidth; + CGFloat screenHeight; + UICollectionViewFlowLayout *portraitLayout; + UICollectionViewFlowLayout *landscapeLayout; } -(id)initWithPicker:(GMImagePickerController *)picker { - //Custom init. The picker contains custom information to create the FlowLayout - self.picker = picker; - - //Ipad popover is not affected by rotation! - if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) + //Custom init. The picker contains custom information to create the FlowLayout + self.picker = picker; + + //Ipad popover is not affected by rotation! + if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) + { + screenWidth = CGRectGetWidth(picker.view.bounds); + screenHeight = CGRectGetHeight(picker.view.bounds); + } + else + { + if(UIInterfaceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation)) { - screenWidth = CGRectGetWidth(picker.view.bounds); - screenHeight = CGRectGetHeight(picker.view.bounds); + screenHeight = CGRectGetWidth(picker.view.bounds); + screenWidth = CGRectGetHeight(picker.view.bounds); } else { - if(UIInterfaceOrientationIsLandscape([UIApplication sharedApplication].statusBarOrientation)) - { - screenHeight = CGRectGetWidth(picker.view.bounds); - screenWidth = CGRectGetHeight(picker.view.bounds); - } - else - { - screenWidth = CGRectGetWidth(picker.view.bounds); - screenHeight = CGRectGetHeight(picker.view.bounds); - } + screenWidth = CGRectGetWidth(picker.view.bounds); + screenHeight = CGRectGetHeight(picker.view.bounds); } + } + + + UICollectionViewFlowLayout *layout = [self collectionViewFlowLayoutForOrientation:[UIApplication sharedApplication].statusBarOrientation]; + if (self = [super initWithCollectionViewLayout:layout]) + { + //Compute the thumbnail pixel size: + CGFloat scale = [UIScreen mainScreen].scale; + //NSLog(@"This is @%fx scale device", scale); + AssetGridThumbnailSize = CGSizeMake(layout.itemSize.width * scale, layout.itemSize.height * scale); + self.collectionView.allowsMultipleSelection = picker.allowsMultipleSelection; - UICollectionViewFlowLayout *layout = [self collectionViewFlowLayoutForOrientation:[UIApplication sharedApplication].statusBarOrientation]; - if (self = [super initWithCollectionViewLayout:layout]) - { - //Compute the thumbnail pixel size: - CGFloat scale = [UIScreen mainScreen].scale; - //NSLog(@"This is @%fx scale device", scale); - AssetGridThumbnailSize = CGSizeMake(layout.itemSize.width * scale, layout.itemSize.height * scale); - - self.collectionView.allowsMultipleSelection = picker.allowsMultipleSelection; - - [self.collectionView registerClass:GMGridViewCell.class - forCellWithReuseIdentifier:GMGridViewCellIdentifier]; - - self.preferredContentSize = kPopoverContentSize; - } + [self.collectionView registerClass:GMGridViewCell.class + forCellWithReuseIdentifier:GMGridViewCellIdentifier]; - return self; + self.preferredContentSize = kPopoverContentSize; + } + + return self; } - (void)viewDidLoad { - [super viewDidLoad]; - [self setupViews]; - - // Navigation bar customization - if (self.picker.customNavigationBarPrompt) { - self.navigationItem.prompt = self.picker.customNavigationBarPrompt; - } - - self.imageManager = [[PHCachingImageManager alloc] init]; - [self resetCachedAssets]; - [[PHPhotoLibrary sharedPhotoLibrary] registerChangeObserver:self]; - - if ([self respondsToSelector:@selector(setEdgesForExtendedLayout:)]) - { - self.edgesForExtendedLayout = UIRectEdgeNone; - } + [super viewDidLoad]; + [self setupViews]; + + // Navigation bar customization + if (self.picker.customNavigationBarPrompt) { + self.navigationItem.prompt = self.picker.customNavigationBarPrompt; + } + + self.imageManager = [[PHCachingImageManager alloc] init]; + [self resetCachedAssets]; + [[PHPhotoLibrary sharedPhotoLibrary] registerChangeObserver:self]; + + if ([self respondsToSelector:@selector(setEdgesForExtendedLayout:)]) + { + self.edgesForExtendedLayout = UIRectEdgeNone; + } } - (void)viewWillAppear:(BOOL)animated { - [super viewWillAppear:animated]; - - [self setupButtons]; - [self setupToolbar]; + [super viewWillAppear:animated]; + + [self setupButtons]; + [self setupToolbar]; } - (void)viewDidAppear:(BOOL)animated { - [super viewDidAppear:animated]; - [self updateCachedAssets]; + [super viewDidAppear:animated]; + [self updateCachedAssets]; } - (void)dealloc { - [self resetCachedAssets]; - [[PHPhotoLibrary sharedPhotoLibrary] unregisterChangeObserver:self]; + [self resetCachedAssets]; + [[PHPhotoLibrary sharedPhotoLibrary] unregisterChangeObserver:self]; } - (UIStatusBarStyle)preferredStatusBarStyle { - return self.picker.pickerStatusBarStyle; + return self.picker.pickerStatusBarStyle; } @@ -164,34 +164,34 @@ - (UIStatusBarStyle)preferredStatusBarStyle { - (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { - if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { - return; - } - - UICollectionViewFlowLayout *layout = [self collectionViewFlowLayoutForOrientation:toInterfaceOrientation]; - - //Update the AssetGridThumbnailSize: - CGFloat scale = [UIScreen mainScreen].scale; - AssetGridThumbnailSize = CGSizeMake(layout.itemSize.width * scale, layout.itemSize.height * scale); - - [self resetCachedAssets]; - //This is optional. Reload visible thumbnails: - for (GMGridViewCell *cell in [self.collectionView visibleCells]) { - NSInteger currentTag = cell.tag; - [self.imageManager requestImageForAsset:cell.asset - targetSize:AssetGridThumbnailSize - contentMode:PHImageContentModeAspectFill - options:nil - resultHandler:^(UIImage *result, NSDictionary *info) - { - // Only update the thumbnail if the cell tag hasn't changed. Otherwise, the cell has been re-used. - if (cell.tag == currentTag) { - [cell.imageView setImage:result]; - } - }]; - } - - [self.collectionView setCollectionViewLayout:layout animated:YES]; + if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { + return; + } + + UICollectionViewFlowLayout *layout = [self collectionViewFlowLayoutForOrientation:toInterfaceOrientation]; + + //Update the AssetGridThumbnailSize: + CGFloat scale = [UIScreen mainScreen].scale; + AssetGridThumbnailSize = CGSizeMake(layout.itemSize.width * scale, layout.itemSize.height * scale); + + [self resetCachedAssets]; + //This is optional. Reload visible thumbnails: + for (GMGridViewCell *cell in [self.collectionView visibleCells]) { + NSInteger currentTag = cell.tag; + [self.imageManager requestImageForAsset:cell.asset + targetSize:AssetGridThumbnailSize + contentMode:PHImageContentModeAspectFill + options:nil + resultHandler:^(UIImage *result, NSDictionary *info) + { + // Only update the thumbnail if the cell tag hasn't changed. Otherwise, the cell has been re-used. + if (cell.tag == currentTag) { + [cell.imageView setImage:result]; + } + }]; + } + + [self.collectionView setCollectionViewLayout:layout animated:YES]; } @@ -199,40 +199,40 @@ - (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInte - (void)setupViews { - self.collectionView.backgroundColor = [UIColor clearColor]; - self.view.backgroundColor = [self.picker pickerBackgroundColor]; + self.collectionView.backgroundColor = [UIColor clearColor]; + self.view.backgroundColor = [self.picker pickerBackgroundColor]; } - (void)setupButtons { - if (self.picker.allowsMultipleSelection) { - NSString *doneTitle = self.picker.customDoneButtonTitle ? self.picker.customDoneButtonTitle : NSLocalizedStringFromTableInBundle(@"picker.navigation.done-button", @"GMImagePicker", [NSBundle bundleForClass:GMImagePickerController.class], @"Done"); - self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:doneTitle - style:UIBarButtonItemStyleDone - target:self.picker - action:@selector(finishPickingAssets:)]; - - self.navigationItem.rightBarButtonItem.enabled = (self.picker.autoDisableDoneButton ? self.picker.selectedAssets.count > 0 : TRUE); - } else { - NSString *cancelTitle = self.picker.customCancelButtonTitle ? self.picker.customCancelButtonTitle : NSLocalizedStringFromTableInBundle(@"picker.navigation.cancel-button", @"GMImagePicker", [NSBundle bundleForClass:GMImagePickerController.class], @"Cancel"); - self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:cancelTitle - style:UIBarButtonItemStyleDone - target:self.picker - action:@selector(dismiss:)]; - } + if (self.picker.allowsMultipleSelection) { + NSString *doneTitle = self.picker.customDoneButtonTitle ? self.picker.customDoneButtonTitle : NSLocalizedStringFromTableInBundle(@"picker.navigation.done-button", @"GMImagePicker", [NSBundle bundleForClass:GMImagePickerController.class], @"Done"); + self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:doneTitle + style:UIBarButtonItemStyleDone + target:self.picker + action:@selector(finishPickingAssets:)]; + + self.navigationItem.rightBarButtonItem.enabled = (self.picker.autoDisableDoneButton ? self.picker.selectedAssets.count > 0 : TRUE); + } else { + NSString *cancelTitle = self.picker.customCancelButtonTitle ? self.picker.customCancelButtonTitle : NSLocalizedStringFromTableInBundle(@"picker.navigation.cancel-button", @"GMImagePicker", [NSBundle bundleForClass:GMImagePickerController.class], @"Cancel"); + self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:cancelTitle + style:UIBarButtonItemStyleDone + target:self.picker + action:@selector(dismiss:)]; + } + if (self.picker.useCustomFontForNavigationBar) { if (self.picker.useCustomFontForNavigationBar) { - if (self.picker.useCustomFontForNavigationBar) { - NSDictionary* barButtonItemAttributes = @{NSFontAttributeName: [UIFont fontWithName:self.picker.pickerFontName size:self.picker.pickerFontHeaderSize]}; - [self.navigationItem.rightBarButtonItem setTitleTextAttributes:barButtonItemAttributes forState:UIControlStateNormal]; - [self.navigationItem.rightBarButtonItem setTitleTextAttributes:barButtonItemAttributes forState:UIControlStateSelected]; - } + NSDictionary* barButtonItemAttributes = @{NSFontAttributeName: [UIFont fontWithName:self.picker.pickerFontName size:self.picker.pickerFontHeaderSize]}; + [self.navigationItem.rightBarButtonItem setTitleTextAttributes:barButtonItemAttributes forState:UIControlStateNormal]; + [self.navigationItem.rightBarButtonItem setTitleTextAttributes:barButtonItemAttributes forState:UIControlStateSelected]; } - + } + } - (void)setupToolbar { - self.toolbarItems = self.picker.toolbarItems; + self.toolbarItems = self.picker.toolbarItems; } @@ -240,54 +240,54 @@ - (void)setupToolbar - (UICollectionViewFlowLayout *)collectionViewFlowLayoutForOrientation:(UIInterfaceOrientation)orientation { - if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) + if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) + { + if(!portraitLayout) + { + portraitLayout = [[UICollectionViewFlowLayout alloc] init]; + portraitLayout.minimumInteritemSpacing = self.picker.minimumInteritemSpacing; + int cellTotalUsableWidth = (int)(screenWidth - (self.picker.colsInPortrait-1)*self.picker.minimumInteritemSpacing); + portraitLayout.itemSize = CGSizeMake(cellTotalUsableWidth/self.picker.colsInPortrait, cellTotalUsableWidth/self.picker.colsInPortrait); + double cellTotalUsedWidth = (double)portraitLayout.itemSize.width*self.picker.colsInPortrait; + double spaceTotalWidth = (double)screenWidth-cellTotalUsedWidth; + double spaceWidth = spaceTotalWidth/(double)(self.picker.colsInPortrait-1); + portraitLayout.minimumLineSpacing = spaceWidth; + } + return portraitLayout; + } + else + { + if(UIInterfaceOrientationIsLandscape(orientation)) { - if(!portraitLayout) - { - portraitLayout = [[UICollectionViewFlowLayout alloc] init]; - portraitLayout.minimumInteritemSpacing = self.picker.minimumInteritemSpacing; - int cellTotalUsableWidth = screenWidth - (self.picker.colsInPortrait-1)*self.picker.minimumInteritemSpacing; - portraitLayout.itemSize = CGSizeMake(cellTotalUsableWidth/self.picker.colsInPortrait, cellTotalUsableWidth/self.picker.colsInPortrait); - double cellTotalUsedWidth = (double)portraitLayout.itemSize.width*self.picker.colsInPortrait; - double spaceTotalWidth = (double)screenWidth-cellTotalUsedWidth; - double spaceWidth = spaceTotalWidth/(double)(self.picker.colsInPortrait-1); - portraitLayout.minimumLineSpacing = spaceWidth; - } - return portraitLayout; + if(!landscapeLayout) + { + landscapeLayout = [[UICollectionViewFlowLayout alloc] init]; + landscapeLayout.minimumInteritemSpacing = self.picker.minimumInteritemSpacing; + int cellTotalUsableWidth = (int)(screenHeight - (self.picker.colsInLandscape-1)*self.picker.minimumInteritemSpacing); + landscapeLayout.itemSize = CGSizeMake(cellTotalUsableWidth/self.picker.colsInLandscape, cellTotalUsableWidth/self.picker.colsInLandscape); + double cellTotalUsedWidth = (double)landscapeLayout.itemSize.width*self.picker.colsInLandscape; + double spaceTotalWidth = (double)screenHeight-cellTotalUsedWidth; + double spaceWidth = spaceTotalWidth/(double)(self.picker.colsInLandscape-1); + landscapeLayout.minimumLineSpacing = spaceWidth; + } + return landscapeLayout; } else { - if(UIInterfaceOrientationIsLandscape(orientation)) - { - if(!landscapeLayout) - { - landscapeLayout = [[UICollectionViewFlowLayout alloc] init]; - landscapeLayout.minimumInteritemSpacing = self.picker.minimumInteritemSpacing; - int cellTotalUsableWidth = screenHeight - (self.picker.colsInLandscape-1)*self.picker.minimumInteritemSpacing; - landscapeLayout.itemSize = CGSizeMake(cellTotalUsableWidth/self.picker.colsInLandscape, cellTotalUsableWidth/self.picker.colsInLandscape); - double cellTotalUsedWidth = (double)landscapeLayout.itemSize.width*self.picker.colsInLandscape; - double spaceTotalWidth = (double)screenHeight-cellTotalUsedWidth; - double spaceWidth = spaceTotalWidth/(double)(self.picker.colsInLandscape-1); - landscapeLayout.minimumLineSpacing = spaceWidth; - } - return landscapeLayout; - } - else - { - if(!portraitLayout) - { - portraitLayout = [[UICollectionViewFlowLayout alloc] init]; - portraitLayout.minimumInteritemSpacing = self.picker.minimumInteritemSpacing; - int cellTotalUsableWidth = screenWidth - (self.picker.colsInPortrait-1)*self.picker.minimumInteritemSpacing; - portraitLayout.itemSize = CGSizeMake(cellTotalUsableWidth/self.picker.colsInPortrait, cellTotalUsableWidth/self.picker.colsInPortrait); - double cellTotalUsedWidth = (double)portraitLayout.itemSize.width*self.picker.colsInPortrait; - double spaceTotalWidth = (double)screenWidth-cellTotalUsedWidth; - double spaceWidth = spaceTotalWidth/(double)(self.picker.colsInPortrait-1); - portraitLayout.minimumLineSpacing = spaceWidth; - } - return portraitLayout; - } + if(!portraitLayout) + { + portraitLayout = [[UICollectionViewFlowLayout alloc] init]; + portraitLayout.minimumInteritemSpacing = self.picker.minimumInteritemSpacing; + int cellTotalUsableWidth = (int)(screenWidth - (self.picker.colsInPortrait-1) * self.picker.minimumInteritemSpacing); + portraitLayout.itemSize = CGSizeMake(cellTotalUsableWidth/self.picker.colsInPortrait, cellTotalUsableWidth/self.picker.colsInPortrait); + double cellTotalUsedWidth = (double)portraitLayout.itemSize.width*self.picker.colsInPortrait; + double spaceTotalWidth = (double)screenWidth-cellTotalUsedWidth; + double spaceWidth = spaceTotalWidth/(double)(self.picker.colsInPortrait-1); + portraitLayout.minimumLineSpacing = spaceWidth; + } + return portraitLayout; } + } } @@ -295,73 +295,73 @@ - (UICollectionViewFlowLayout *)collectionViewFlowLayoutForOrientation:(UIInterf - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView { - return 1; + return 1; } - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { - GMGridViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:GMGridViewCellIdentifier - forIndexPath:indexPath]; - - // Increment the cell's tag - NSInteger currentTag = cell.tag + 1; - cell.tag = currentTag; - - PHAsset *asset = self.assetsFetchResults[indexPath.item]; - - /*if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) - { - NSLog(@"Image manager: Requesting FIT image for iPad"); - [self.imageManager requestImageForAsset:asset - targetSize:AssetGridThumbnailSize - contentMode:PHImageContentModeAspectFit - options:nil - resultHandler:^(UIImage *result, NSDictionary *info) { - - // Only update the thumbnail if the cell tag hasn't changed. Otherwise, the cell has been re-used. - if (cell.tag == currentTag) { - [cell.imageView setImage:result]; - } - }]; - } - else*/ - { - //NSLog(@"Image manager: Requesting FILL image for iPhone"); - [self.imageManager requestImageForAsset:asset - targetSize:AssetGridThumbnailSize - contentMode:PHImageContentModeAspectFill - options:nil - resultHandler:^(UIImage *result, NSDictionary *info) { - - // Only update the thumbnail if the cell tag hasn't changed. Otherwise, the cell has been re-used. - if (cell.tag == currentTag) { - [cell.imageView setImage:result]; - } - }]; - } - - - [cell bind:asset]; - - cell.shouldShowSelection = self.picker.allowsMultipleSelection; - - // Optional protocol to determine if some kind of assets can't be selected (pej long videos, etc...) - if ([self.picker.delegate respondsToSelector:@selector(assetsPickerController:shouldEnableAsset:)]) { - cell.enabled = [self.picker.delegate assetsPickerController:self.picker shouldEnableAsset:asset]; - } else { - cell.enabled = YES; - } - - // 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; - [collectionView selectItemAtIndexPath:indexPath animated:NO scrollPosition:UICollectionViewScrollPositionNone]; - } else { - cell.selected = NO; - } - - return cell; + GMGridViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:GMGridViewCellIdentifier + forIndexPath:indexPath]; + + // Increment the cell's tag + NSInteger currentTag = cell.tag + 1; + cell.tag = currentTag; + + PHAsset *asset = self.assetsFetchResults[(NSUInteger)indexPath.item]; + + /*if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) + { + NSLog(@"Image manager: Requesting FIT image for iPad"); + [self.imageManager requestImageForAsset:asset + targetSize:AssetGridThumbnailSize + contentMode:PHImageContentModeAspectFit + options:nil + resultHandler:^(UIImage *result, NSDictionary *info) { + + // Only update the thumbnail if the cell tag hasn't changed. Otherwise, the cell has been re-used. + if (cell.tag == currentTag) { + [cell.imageView setImage:result]; + } + }]; + } + else*/ + { + //NSLog(@"Image manager: Requesting FILL image for iPhone"); + [self.imageManager requestImageForAsset:asset + targetSize:AssetGridThumbnailSize + contentMode:PHImageContentModeAspectFill + options:nil + resultHandler:^(UIImage *result, NSDictionary *info) { + + // Only update the thumbnail if the cell tag hasn't changed. Otherwise, the cell has been re-used. + if (cell.tag == currentTag) { + [cell.imageView setImage:result]; + } + }]; + } + + + [cell bind:asset]; + + cell.shouldShowSelection = self.picker.allowsMultipleSelection; + + // Optional protocol to determine if some kind of assets can't be selected (pej long videos, etc...) + if ([self.picker.delegate respondsToSelector:@selector(assetsPickerController:shouldEnableAsset:)]) { + cell.enabled = [self.picker.delegate assetsPickerController:self.picker shouldEnableAsset:asset]; + } else { + cell.enabled = YES; + } + + // 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; + [collectionView selectItemAtIndexPath:indexPath animated:NO scrollPosition:UICollectionViewScrollPositionNone]; + } else { + cell.selected = NO; + } + + return cell; } @@ -369,79 +369,79 @@ - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cell - (BOOL)collectionView:(UICollectionView *)collectionView shouldSelectItemAtIndexPath:(NSIndexPath *)indexPath { - PHAsset *asset = self.assetsFetchResults[indexPath.item]; - - GMGridViewCell *cell = (GMGridViewCell *)[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; - } + PHAsset *asset = self.assetsFetchResults[(NSUInteger)indexPath.item]; + + GMGridViewCell *cell = (GMGridViewCell *)[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.assetsFetchResults[indexPath.item]; - - [self.picker selectAsset:asset]; - - if ([self.picker.delegate respondsToSelector:@selector(assetsPickerController:didSelectAsset:)]) { - [self.picker.delegate assetsPickerController:self.picker didSelectAsset:asset]; - } + PHAsset *asset = self.assetsFetchResults[(NSUInteger)indexPath.item]; + + [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.assetsFetchResults[indexPath.item]; - - if ([self.picker.delegate respondsToSelector:@selector(assetsPickerController:shouldDeselectAsset:)]) { - return [self.picker.delegate assetsPickerController:self.picker shouldDeselectAsset:asset]; - } else { - return YES; - } + PHAsset *asset = self.assetsFetchResults[(NSUInteger)indexPath.item]; + + 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.assetsFetchResults[indexPath.item]; - - [self.picker deselectAsset:asset]; - - if ([self.picker.delegate respondsToSelector:@selector(assetsPickerController:didDeselectAsset:)]) { - [self.picker.delegate assetsPickerController:self.picker didDeselectAsset:asset]; - } + PHAsset *asset = self.assetsFetchResults[(NSUInteger)indexPath.item]; + + [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.assetsFetchResults[indexPath.item]; - - if ([self.picker.delegate respondsToSelector:@selector(assetsPickerController:shouldHighlightAsset:)]) { - return [self.picker.delegate assetsPickerController:self.picker shouldHighlightAsset:asset]; - } else { - return YES; - } + PHAsset *asset = self.assetsFetchResults[(NSUInteger)indexPath.item]; + + 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.assetsFetchResults[indexPath.item]; - - if ([self.picker.delegate respondsToSelector:@selector(assetsPickerController:didHighlightAsset:)]) { - [self.picker.delegate assetsPickerController:self.picker didHighlightAsset:asset]; - } + PHAsset *asset = self.assetsFetchResults[(NSUInteger)indexPath.item]; + + 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.assetsFetchResults[indexPath.item]; - - if ([self.picker.delegate respondsToSelector:@selector(assetsPickerController:didUnhighlightAsset:)]) { - [self.picker.delegate assetsPickerController:self.picker didUnhighlightAsset:asset]; - } + PHAsset *asset = self.assetsFetchResults[(NSUInteger)indexPath.item]; + + if ([self.picker.delegate respondsToSelector:@selector(assetsPickerController:didUnhighlightAsset:)]) { + [self.picker.delegate assetsPickerController:self.picker didUnhighlightAsset:asset]; + } } @@ -450,8 +450,8 @@ - (void)collectionView:(UICollectionView *)collectionView didUnhighlightItemAtIn - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section { - NSInteger count = self.assetsFetchResults.count; - return count; + NSInteger count = (NSInteger)self.assetsFetchResults.count; + return count; } @@ -459,48 +459,48 @@ - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSe - (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(), ^{ + // Call might come on any background queue. Re-dispatch to the main queue to handle it. + dispatch_async(dispatch_get_main_queue(), ^{ + + // check if there are changes to the assets (insertions, deletions, updates) + PHFetchResultChangeDetails *collectionChanges = [changeInstance changeDetailsForFetchResult:self.assetsFetchResults]; + if (collectionChanges) { + + // get the new fetch result + self.assetsFetchResults = [collectionChanges fetchResultAfterChanges]; + + UICollectionView *collectionView = self.collectionView; + + if (![collectionChanges hasIncrementalChanges] || [collectionChanges hasMoves]) { + // we need to reload all if the incremental diffs are not available + [collectionView reloadData]; - // check if there are changes to the assets (insertions, deletions, updates) - PHFetchResultChangeDetails *collectionChanges = [changeInstance changeDetailsForFetchResult:self.assetsFetchResults]; - if (collectionChanges) { - - // get the new fetch result - self.assetsFetchResults = [collectionChanges fetchResultAfterChanges]; - - UICollectionView *collectionView = self.collectionView; - - if (![collectionChanges hasIncrementalChanges] || [collectionChanges hasMoves]) { - // we need to reload all if the incremental diffs are not available - [collectionView reloadData]; - - } else { - // if we have incremental diffs, tell the collection view to animate insertions and deletions - [collectionView performBatchUpdates:^{ - NSIndexSet *removedIndexes = [collectionChanges removedIndexes]; - if ([removedIndexes count]) { - [collectionView deleteItemsAtIndexPaths:[removedIndexes aapl_indexPathsFromIndexesWithSection:0]]; - } - NSIndexSet *insertedIndexes = [collectionChanges insertedIndexes]; - if ([insertedIndexes count]) { - [collectionView insertItemsAtIndexPaths:[insertedIndexes aapl_indexPathsFromIndexesWithSection:0]]; - if (self.picker.showCameraButton && self.picker.autoSelectCameraImages) { - for (NSIndexPath *path in [insertedIndexes aapl_indexPathsFromIndexesWithSection:0]) { - [self collectionView:collectionView didSelectItemAtIndexPath:path]; - } - } - } - NSIndexSet *changedIndexes = [collectionChanges changedIndexes]; - if ([changedIndexes count]) { - [collectionView reloadItemsAtIndexPaths:[changedIndexes aapl_indexPathsFromIndexesWithSection:0]]; - } - } completion:NULL]; + } else { + // if we have incremental diffs, tell the collection view to animate insertions and deletions + [collectionView performBatchUpdates:^{ + NSIndexSet *removedIndexes = [collectionChanges removedIndexes]; + if ([removedIndexes count]) { + [collectionView deleteItemsAtIndexPaths:[removedIndexes aapl_indexPathsFromIndexesWithSection:0]]; + } + NSIndexSet *insertedIndexes = [collectionChanges insertedIndexes]; + if ([insertedIndexes count]) { + [collectionView insertItemsAtIndexPaths:[insertedIndexes aapl_indexPathsFromIndexesWithSection:0]]; + if (self.picker.showCameraButton && self.picker.autoSelectCameraImages) { + for (NSIndexPath *path in [insertedIndexes aapl_indexPathsFromIndexesWithSection:0]) { + [self collectionView:collectionView didSelectItemAtIndexPath:path]; + } } - - [self resetCachedAssets]; - } - }); + } + NSIndexSet *changedIndexes = [collectionChanges changedIndexes]; + if ([changedIndexes count]) { + [collectionView reloadItemsAtIndexPaths:[changedIndexes aapl_indexPathsFromIndexesWithSection:0]]; + } + } completion:NULL]; + } + + [self resetCachedAssets]; + } + }); } @@ -508,7 +508,7 @@ - (void)photoLibraryDidChange:(PHChange *)changeInstance - (void)scrollViewDidScroll:(UIScrollView *)scrollView { - [self updateCachedAssets]; + [self updateCachedAssets]; } @@ -516,91 +516,91 @@ - (void)scrollViewDidScroll:(UIScrollView *)scrollView - (void)resetCachedAssets { - [self.imageManager stopCachingImagesForAllAssets]; - self.previousPreheatRect = CGRectZero; + [self.imageManager stopCachingImagesForAllAssets]; + self.previousPreheatRect = CGRectZero; } - (void)updateCachedAssets { - BOOL isViewVisible = [self isViewLoaded] && [[self view] window] != nil; - if (!isViewVisible) { return; } + 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 aapl_indexPathsForElementsInRect:removedRect]; + [removedIndexPaths addObjectsFromArray:indexPaths]; + } addedHandler:^(CGRect addedRect) { + NSArray *indexPaths = [self.collectionView aapl_indexPathsForElementsInRect:addedRect]; + [addedIndexPaths addObjectsFromArray:indexPaths]; + }]; - // 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)); + NSArray *assetsToStartCaching = [self assetsAtIndexPaths:addedIndexPaths]; + NSArray *assetsToStopCaching = [self assetsAtIndexPaths:removedIndexPaths]; - // 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 aapl_indexPathsForElementsInRect:removedRect]; - [removedIndexPaths addObjectsFromArray:indexPaths]; - } addedHandler:^(CGRect addedRect) { - NSArray *indexPaths = [self.collectionView aapl_indexPathsForElementsInRect:addedRect]; - [addedIndexPaths addObjectsFromArray:indexPaths]; - }]; - - NSArray *assetsToStartCaching = [self assetsAtIndexPaths:addedIndexPaths]; - NSArray *assetsToStopCaching = [self assetsAtIndexPaths:removedIndexPaths]; - - [self.imageManager startCachingImagesForAssets:assetsToStartCaching - targetSize:AssetGridThumbnailSize - contentMode:PHImageContentModeAspectFill - options:nil]; - [self.imageManager stopCachingImagesForAssets:assetsToStopCaching - targetSize:AssetGridThumbnailSize - contentMode:PHImageContentModeAspectFill - options:nil]; - - self.previousPreheatRect = preheatRect; - } + [self.imageManager startCachingImagesForAssets:assetsToStartCaching + targetSize:AssetGridThumbnailSize + contentMode:PHImageContentModeAspectFill + options:nil]; + [self.imageManager stopCachingImagesForAssets:assetsToStopCaching + targetSize:AssetGridThumbnailSize + contentMode:PHImageContentModeAspectFill + options:nil]; + + self.previousPreheatRect = preheatRect; + } } - (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); + 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) { - PHAsset *asset = self.assetsFetchResults[indexPath.item]; - [assets addObject:asset]; - } - return assets; + if (indexPaths.count == 0) { return nil; } + + NSMutableArray *assets = [NSMutableArray arrayWithCapacity:indexPaths.count]; + for (NSIndexPath *indexPath in indexPaths) { + PHAsset *asset = self.assetsFetchResults[(NSUInteger)indexPath.item]; + [assets addObject:asset]; + } + return assets; } -@end \ No newline at end of file +@end diff --git a/GMImagePicker/GMImagePickerController.h b/GMImagePicker/GMImagePickerController.h index a68dddd..e88fe75 100644 --- a/GMImagePicker/GMImagePickerController.h +++ b/GMImagePicker/GMImagePickerController.h @@ -6,8 +6,8 @@ // Copyright (c) 2014 Guillermo Muntaner Perelló. All rights reserved. // -@import UIKit; -@import Photos; +#import +#import //This is the default image picker size! @@ -41,7 +41,7 @@ static CGSize const kPopoverContentSize = {480, 720}; /** * Determines which smart collections are displayed (int array of enum: PHAssetCollectionSubtypeSmartAlbum) - * The default smart collections are: + * The default smart collections are: * - Favorites * - RecentlyAdded * - Videos @@ -318,4 +318,4 @@ static CGSize const kPopoverContentSize = {480, 720}; -@end \ No newline at end of file +@end diff --git a/GMImagePicker/GMImagePickerController.m b/GMImagePicker/GMImagePickerController.m index 2be9e2e..b999192 100644 --- a/GMImagePicker/GMImagePickerController.m +++ b/GMImagePicker/GMImagePickerController.m @@ -9,7 +9,7 @@ #import #import "GMImagePickerController.h" #import "GMAlbumsViewController.h" -@import Photos; +#import @interface GMImagePickerController () From f78e8788928db257b4a5579fc4f033d60d124ec2 Mon Sep 17 00:00:00 2001 From: "dinesh.kumar" Date: Mon, 18 Sep 2017 17:00:00 +0530 Subject: [PATCH 4/7] bump version 0.0.3 --- GMImagePicker.podspec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/GMImagePicker.podspec b/GMImagePicker.podspec index 1e27e9c..61d745a 100644 --- a/GMImagePicker.podspec +++ b/GMImagePicker.podspec @@ -16,7 +16,7 @@ Pod::Spec.new do |s| # s.name = "GMImagePicker" - s.version = "0.0.2" + s.version = “0.0.3” s.summary = "A Photo and Video picker similar to UIImagePicker supporting multiple selections and UI customizations." s.description = "GMImagePicker is a tiny and fast UIImagePicker replacement supporting video picking, multiple selections and UI customizations. It is based in the new PhotoKit framework and returns an array of PHAssets so only works for iOS 8+" @@ -35,7 +35,7 @@ Pod::Spec.new do |s| s.platform = :ios, "8.0" # ――― Source Location ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # - s.source = { :git => "https://github.com/guillermomuntaner/GMImagePicker.git", :tag => "0.0.2" } + s.source = { :git => "https://github.com/guillermomuntaner/GMImagePicker.git", :tag => “0.0.3” } # ――― Source Code ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # s.source_files = "GMImagePicker", "GMImagePicker/*.{h,m}" From 03a6336a1f4b48d467021befb42e9d3dca711aba Mon Sep 17 00:00:00 2001 From: "dinesh.kumar" Date: Mon, 18 Sep 2017 17:29:00 +0530 Subject: [PATCH 5/7] Fixed the source --- GMImagePicker.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GMImagePicker.podspec b/GMImagePicker.podspec index 61d745a..5dc4e26 100644 --- a/GMImagePicker.podspec +++ b/GMImagePicker.podspec @@ -35,7 +35,7 @@ Pod::Spec.new do |s| s.platform = :ios, "8.0" # ――― Source Location ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # - s.source = { :git => "https://github.com/guillermomuntaner/GMImagePicker.git", :tag => “0.0.3” } + s.source = { :git => "https://github.com/hudinwal/GMImagePicker.git", :tag => "v#{s.version.to_s}" } # ――― Source Code ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # s.source_files = "GMImagePicker", "GMImagePicker/*.{h,m}" From d38da559f2448860ce9e9b6f41a72ed6192959bf Mon Sep 17 00:00:00 2001 From: "dinesh.kumar" Date: Tue, 19 Sep 2017 11:11:12 +0530 Subject: [PATCH 6/7] Revert to 0.0.2 in pod spec --- GMImagePicker.podspec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/GMImagePicker.podspec b/GMImagePicker.podspec index 5dc4e26..6efd6b9 100644 --- a/GMImagePicker.podspec +++ b/GMImagePicker.podspec @@ -16,7 +16,7 @@ Pod::Spec.new do |s| # s.name = "GMImagePicker" - s.version = “0.0.3” + s.version = “0.0.2” s.summary = "A Photo and Video picker similar to UIImagePicker supporting multiple selections and UI customizations." s.description = "GMImagePicker is a tiny and fast UIImagePicker replacement supporting video picking, multiple selections and UI customizations. It is based in the new PhotoKit framework and returns an array of PHAssets so only works for iOS 8+" @@ -35,7 +35,7 @@ Pod::Spec.new do |s| s.platform = :ios, "8.0" # ――― Source Location ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # - s.source = { :git => "https://github.com/hudinwal/GMImagePicker.git", :tag => "v#{s.version.to_s}" } + s.source = { :git => "https://github.com/hudinwal/GMImagePicker.git" } # ――― Source Code ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # s.source_files = "GMImagePicker", "GMImagePicker/*.{h,m}" From d17a913a2e2e56a48939bae1e265eb98b01d62f6 Mon Sep 17 00:00:00 2001 From: "dinesh.kumar" Date: Tue, 19 Sep 2017 11:20:23 +0530 Subject: [PATCH 7/7] Trying to fix "[!] Unable to find a specification for 'GMImagePicker'. [!] Unable to load a podspec from `GMImagePicker.podspec`, skipping:" --- GMImagePicker.podspec | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/GMImagePicker.podspec b/GMImagePicker.podspec index 6efd6b9..e7b41ce 100644 --- a/GMImagePicker.podspec +++ b/GMImagePicker.podspec @@ -16,7 +16,7 @@ Pod::Spec.new do |s| # s.name = "GMImagePicker" - s.version = “0.0.2” + s.version = "0.0.2" s.summary = "A Photo and Video picker similar to UIImagePicker supporting multiple selections and UI customizations." s.description = "GMImagePicker is a tiny and fast UIImagePicker replacement supporting video picking, multiple selections and UI customizations. It is based in the new PhotoKit framework and returns an array of PHAssets so only works for iOS 8+" @@ -35,7 +35,7 @@ Pod::Spec.new do |s| s.platform = :ios, "8.0" # ――― Source Location ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # - s.source = { :git => "https://github.com/hudinwal/GMImagePicker.git" } + s.source = { :git => "https://github.com/guillermomuntaner/GMImagePicker.git", :tag => "0.0.2" } # ――― Source Code ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # s.source_files = "GMImagePicker", "GMImagePicker/*.{h,m}" @@ -59,4 +59,4 @@ Pod::Spec.new do |s| # s.xcconfig = { "HEADER_SEARCH_PATHS" => "$(SDKROOT)/usr/include/libxml2" } # s.dependency "JSONKit", "~> 1.4" -end +end \ No newline at end of file