diff --git a/Classes/ELCImagePicker/ELCAlbumPickerController.h b/Classes/ELCImagePicker/ELCAlbumPickerController.h index 1c41414..bc081e9 100755 --- a/Classes/ELCImagePicker/ELCAlbumPickerController.h +++ b/Classes/ELCImagePicker/ELCAlbumPickerController.h @@ -10,6 +10,8 @@ #import "ELCAssetSelectionDelegate.h" #import "ELCAssetPickerFilterDelegate.h" + + @interface ELCAlbumPickerController : UITableViewController @property (nonatomic, weak) id parent; diff --git a/Classes/ELCImagePicker/ELCAlbumPickerController.m b/Classes/ELCImagePicker/ELCAlbumPickerController.m index e375a0a..53d3a10 100755 --- a/Classes/ELCImagePicker/ELCAlbumPickerController.m +++ b/Classes/ELCImagePicker/ELCAlbumPickerController.m @@ -9,13 +9,20 @@ #import "ELCImagePickerController.h" #import "ELCAssetTablePicker.h" #import +#import +#import "ELCConstants.h" +#import "ELCConsole.h" -@interface ELCAlbumPickerController () + +@interface ELCAlbumPickerController () @property (nonatomic, strong) ALAssetsLibrary *library; +@property (strong) PHCachingImageManager *imageManager; @end +static CGSize const kAlbumThumbnailSize1 = {70.0f , 70.0f}; + @implementation ELCAlbumPickerController //Using auto synthesizers @@ -38,69 +45,161 @@ - (void)viewDidLoad ALAssetsLibrary *assetLibrary = [[ALAssetsLibrary alloc] init]; self.library = assetLibrary; + + self.imageManager = [[PHCachingImageManager alloc] init]; // Load Albums into assetGroups - dispatch_async(dispatch_get_main_queue(), ^ - { - @autoreleasepool { - - // Group enumerator Block - void (^assetGroupEnumerator)(ALAssetsGroup *, BOOL *) = ^(ALAssetsGroup *group, BOOL *stop) - { - if (group == nil) { - return; - } + if(!IS_IOS8) { + dispatch_async(dispatch_get_main_queue(), ^ + { + @autoreleasepool { + + // Group enumerator Block - // added fix for camera albums order - NSString *sGroupPropertyName = (NSString *)[group valueForProperty:ALAssetsGroupPropertyName]; - NSUInteger nType = [[group valueForProperty:ALAssetsGroupPropertyType] intValue]; + void (^assetGroupEnumerator)(ALAssetsGroup *, BOOL *) = ^(ALAssetsGroup *group, BOOL *stop) + { + if (group == nil) { + return; + } + + // added fix for camera albums order + NSString *sGroupPropertyName = (NSString *)[group valueForProperty:ALAssetsGroupPropertyName]; + NSUInteger nType = [[group valueForProperty:ALAssetsGroupPropertyType] intValue]; + + if ([[sGroupPropertyName lowercaseString] isEqualToString:@"camera roll"] && nType == ALAssetsGroupSavedPhotos) { + [self.assetGroups insertObject:group atIndex:0]; + } + else { + [self.assetGroups addObject:group]; + } + + // Reload albums + [self performSelectorOnMainThread:@selector(reloadTableView) withObject:nil waitUntilDone:YES]; + }; - if ([[sGroupPropertyName lowercaseString] isEqualToString:@"camera roll"] && nType == ALAssetsGroupSavedPhotos) { - [self.assetGroups insertObject:group atIndex:0]; - } - else { - [self.assetGroups addObject:group]; - } - - // Reload albums - [self performSelectorOnMainThread:@selector(reloadTableView) withObject:nil waitUntilDone:YES]; - }; - - // Group Enumerator Failure Block - void (^assetGroupEnumberatorFailure)(NSError *) = ^(NSError *error) { - - if ([ALAssetsLibrary authorizationStatus] == ALAuthorizationStatusDenied) { - NSString *errorMessage = NSLocalizedString(@"This app does not have access to your photos or videos. You can enable access in Privacy Settings.", nil); - [[[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Access Denied", nil) message:errorMessage delegate:nil cancelButtonTitle:NSLocalizedString(@"Ok", nil) otherButtonTitles:nil] show]; + // Group Enumerator Failure Block + void (^assetGroupEnumberatorFailure)(NSError *) = ^(NSError *error) { - } else { - NSString *errorMessage = [NSString stringWithFormat:@"Album Error: %@ - %@", [error localizedDescription], [error localizedRecoverySuggestion]]; - [[[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Error", nil) message:errorMessage delegate:nil cancelButtonTitle:NSLocalizedString(@"Ok", nil) otherButtonTitles:nil] show]; - } + if ([ALAssetsLibrary authorizationStatus] == ALAuthorizationStatusDenied) { + NSString *errorMessage = NSLocalizedString(@"This app does not have access to your photos or videos. You can enable access in Privacy Settings.", nil); + [[[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Access Denied", nil) message:errorMessage delegate:nil cancelButtonTitle:NSLocalizedString(@"Ok", nil) otherButtonTitles:nil] show]; + + } else { + NSString *errorMessage = [NSString stringWithFormat:@"Album Error: %@ - %@", [error localizedDescription], [error localizedRecoverySuggestion]]; + [[[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Error", nil) message:errorMessage delegate:nil cancelButtonTitle:NSLocalizedString(@"Ok", nil) otherButtonTitles:nil] show]; + } + + [self.navigationItem setTitle:nil]; + NSLog(@"A problem occured %@", [error description]); + }; + + // Enumerate Albums + + [self.library enumerateGroupsWithTypes:ALAssetsGroupAll + usingBlock:assetGroupEnumerator + failureBlock:assetGroupEnumberatorFailure]; + + } + }); + } else { +// //if ios 8 and above + NSLog(@"authorization status %li", (long)[PHPhotoLibrary authorizationStatus]); + [[PHPhotoLibrary sharedPhotoLibrary] registerChangeObserver:self]; +// [self updateFetchResults]; + } +} - [self.navigationItem setTitle:nil]; - NSLog(@"A problem occured %@", [error description]); - }; - - // Enumerate Albums - [self.library enumerateGroupsWithTypes:ALAssetsGroupAll - usingBlock:assetGroupEnumerator - failureBlock:assetGroupEnumberatorFailure]; - - } - }); +-(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.assetGroups removeAllObjects]; + + BOOL ascending = [[ELCConsole mainConsole] sortImagesAscendingByDates]; + + //Fetch PHAssetCollections: + PHFetchOptions *options = [[PHFetchOptions alloc] init]; + options.predicate = [NSPredicate predicateWithFormat:@"mediaType in %@", @[@(PHAssetMediaTypeImage)]]; + options.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:ascending]]; + PHFetchResult *assetsFetchResult = [PHAsset fetchAssetsWithOptions:options]; + + if (assetsFetchResult != nil) + [self.assetGroups addObject:@{@"All Photos":assetsFetchResult}]; + + + PHFetchResult * topLevelUserCollections = [PHAssetCollection fetchTopLevelUserCollectionsWithOptions:nil]; + + [self addCollectionsToGroups:self.assetGroups + usingFetchResult:topLevelUserCollections + sortPhotosAscending:ascending]; + PHFetchResult * cloudUserCollections = + [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum + subtype:PHAssetCollectionSubtypeAlbumCloudShared + options:nil]; + + [self addCollectionsToGroups:self.assetGroups + usingFetchResult:cloudUserCollections + sortPhotosAscending:ascending]; + + PHFetchResult * photoStreamUserCollections = + [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum + subtype:PHAssetCollectionSubtypeAlbumMyPhotoStream + options:nil]; + + [self addCollectionsToGroups:self.assetGroups + usingFetchResult:photoStreamUserCollections + sortPhotosAscending:ascending]; + + [self reloadTableView]; +} + +- (void)addCollectionsToGroups:(NSMutableArray *)groups + usingFetchResult:(PHFetchResult *)fetchResult + sortPhotosAscending:(BOOL)ascending { + for(PHCollection * collection in fetchResult) + { + if ([collection isKindOfClass:[PHAssetCollection class]]) + { + PHFetchOptions *options = [[PHFetchOptions alloc] init]; + options.predicate = [NSPredicate predicateWithFormat:@"mediaType in %@", @[@(PHAssetMediaTypeImage)]]; + options.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" + ascending:ascending]]; + PHAssetCollection *assetCollection = (PHAssetCollection *)collection; + + //Albums collections are allways PHAssetCollectionType=1 & PHAssetCollectionSubtype=2 + + PHFetchResult *assetsFetchResult = [PHAsset fetchAssetsInAssetCollection:assetCollection options:options]; + [self.assetGroups addObject:@{collection.localizedTitle : assetsFetchResult}]; + } + } } - (void)viewWillAppear:(BOOL)animated { - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reloadTableView) name:ALAssetsLibraryChangedNotification object:nil]; + if(!IS_IOS8) { + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reloadTableView) name:ALAssetsLibraryChangedNotification object:nil]; + }else { + //if ios 8 and above + [self updateFetchResults]; + + } + + [self.tableView reloadData]; } - (void)viewWillDisappear:(BOOL)animated { - - [[NSNotificationCenter defaultCenter] removeObserver:self name:ALAssetsLibraryChangedNotification object:nil]; + if(!IS_IOS8) { + [[NSNotificationCenter defaultCenter] removeObserver:self name:ALAssetsLibraryChangedNotification object:nil]; + } +} + +- (void)dealloc +{ + [[PHPhotoLibrary sharedPhotoLibrary] unregisterChangeObserver:self]; } - (void)reloadTableView @@ -167,17 +266,60 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; } - // Get count - ALAssetsGroup *g = (ALAssetsGroup*)[self.assetGroups objectAtIndex:indexPath.row]; - [g setAssetsFilter:[self assetFilter]]; - NSInteger gCount = [g numberOfAssets]; + // Increment the cell's tag + NSInteger currentTag = cell.tag + 1; + cell.tag = currentTag; - cell.textLabel.text = [NSString stringWithFormat:@"%@ (%ld)",[g valueForProperty:ALAssetsGroupPropertyName], (long)gCount]; - UIImage* image = [UIImage imageWithCGImage:[g posterImage]]; - image = [self resize:image to:CGSizeMake(78, 78)]; - [cell.imageView setImage:image]; - [cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator]; - +// if(indexPath.row == 0) { + +// ALAssetsGroup *g = (ALAssetsGroup*)[self.assetGroups objectAtIndex:indexPath.row-1]; +// [g setAssetsFilter:[self assetFilter]]; +// NSInteger gCount = [g numberOfAssets]; +// +// cell.textLabel.text = [NSString stringWithFormat:@"%@ (%ld)",[g valueForProperty:ALAssetsGroupPropertyName], (long)gCount]; +// UIImage* image = [UIImage imageWithCGImage:[g posterImage]]; +// image = [self resize:image to:CGSizeMake(78, 78)]; +// [cell.imageView setImage:image]; +// [cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator]; + + + // } else { if ios 8 and above + NSDictionary *currentFetchResultRecord = [self.assetGroups objectAtIndex:indexPath.row]; + PHFetchResult *assetsFetchResult = [currentFetchResultRecord allValues][0]; + cell.textLabel.text = [NSString stringWithFormat:@"%@ %lu", [currentFetchResultRecord allKeys][0],(unsigned long)assetsFetchResult.count]; + 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]; + + PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init]; + + // Download from cloud if necessary + options.networkAccessAllowed = YES; + options.deliveryMode = PHImageRequestOptionsDeliveryModeFastFormat; + options.progressHandler = ^(double progress, NSError *error, BOOL *stop, NSDictionary *info) { + + }; + + [self.imageManager requestImageForAsset:asset + targetSize:tableCellThumbnailSize1 + contentMode:PHImageContentModeAspectFill + options:options + resultHandler:^(UIImage *result, NSDictionary *info) + { + if(cell.tag == currentTag) { + cell.imageView.image = [result copy]; + [cell setNeedsLayout]; + } + }]; + }else { + cell.imageView.image = nil; + } + + return cell; } @@ -201,9 +343,13 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath ELCAssetTablePicker *picker = [[ELCAssetTablePicker alloc] initWithNibName: nil bundle: nil]; picker.parent = self; - picker.assetGroup = [self.assetGroups objectAtIndex:indexPath.row]; - [picker.assetGroup setAssetsFilter:[self assetFilter]]; + if(!IS_IOS8) { + picker.assetGroup = [self.assetGroups objectAtIndex:indexPath.row]; + [((ALAssetsGroup *)picker.assetGroup) setAssetsFilter:[self assetFilter]]; + }else { + picker.assetGroup = [[self.assetGroups objectAtIndex:indexPath.row] allValues][0]; + } picker.assetPickerFilterDelegate = self.assetPickerFilterDelegate; [self.navigationController pushViewController:picker animated:YES]; @@ -214,5 +360,35 @@ - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPa return 95; } + +#pragma mark - Photos Observer + +- (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 (NSDictionary *fetchResultDictionary in self.assetGroups) { + PHFetchResult *collectionsFetchResult = [fetchResultDictionary allValues][0]; + PHFetchResultChangeDetails *changeDetails = [changeInstance changeDetailsForFetchResult:collectionsFetchResult]; + if (changeDetails) { + + if (!updatedCollectionsFetchResults) { + updatedCollectionsFetchResults = [self.assetGroups mutableCopy]; + } + + [updatedCollectionsFetchResults replaceObjectAtIndex:[self.assetGroups indexOfObject:fetchResultDictionary] withObject:@{[fetchResultDictionary allKeys][0] :[changeDetails fetchResultAfterChanges]}]; + } + } + + if (updatedCollectionsFetchResults) { + self.assetGroups = updatedCollectionsFetchResults; + [self.tableView reloadData]; + } + + }); +} @end diff --git a/Classes/ELCImagePicker/ELCAsset.h b/Classes/ELCImagePicker/ELCAsset.h index b812d77..f35a162 100755 --- a/Classes/ELCImagePicker/ELCAsset.h +++ b/Classes/ELCImagePicker/ELCAsset.h @@ -22,11 +22,11 @@ @interface ELCAsset : NSObject -@property (nonatomic, strong) ALAsset *asset; +@property (nonatomic, strong) NSObject *asset; @property (nonatomic, weak) id parent; @property (nonatomic, assign) BOOL selected; @property (nonatomic,assign) int index; -- (id)initWithAsset:(ALAsset *)asset; +- (id)initWithAsset:(NSObject *)asset; - (NSComparisonResult)compareWithIndex:(ELCAsset *)_ass; @end \ No newline at end of file diff --git a/Classes/ELCImagePicker/ELCAsset.m b/Classes/ELCImagePicker/ELCAsset.m index a664192..085ee2c 100755 --- a/Classes/ELCImagePicker/ELCAsset.m +++ b/Classes/ELCImagePicker/ELCAsset.m @@ -16,7 +16,7 @@ - (NSString *)description return [NSString stringWithFormat:@"ELCAsset index:%d",self.index]; } -- (id)initWithAsset:(ALAsset*)asset +- (id)initWithAsset:(NSObject*)asset { self = [super init]; if (self) { diff --git a/Classes/ELCImagePicker/ELCAssetCell.m b/Classes/ELCImagePicker/ELCAssetCell.m index d456b11..59f6f4f 100755 --- a/Classes/ELCImagePicker/ELCAssetCell.m +++ b/Classes/ELCImagePicker/ELCAssetCell.m @@ -9,12 +9,15 @@ #import "ELCAsset.h" #import "ELCConsole.h" #import "ELCOverlayImageView.h" +#import "ELCConstants.h" +#import @interface ELCAssetCell () @property (nonatomic, strong) NSArray *rowAssets; @property (nonatomic, strong) NSMutableArray *imageViewArray; @property (nonatomic, strong) NSMutableArray *overlayViewArray; +@property (strong) PHCachingImageManager *imageManager; @end @@ -36,6 +39,7 @@ - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reus self.overlayViewArray = overlayArray; self.alignmentLeft = YES; + self.imageManager = [[PHCachingImageManager alloc] init]; } return self; } @@ -50,32 +54,84 @@ - (void)setAssets:(NSArray *)assets [view removeFromSuperview]; } //set up a pointer here so we don't keep calling [UIImage imageNamed:] if creating overlays - UIImage *overlayImage = nil; - for (int i = 0; i < [_rowAssets count]; ++i) { + + if(!IS_IOS8){ + UIImage *overlayImage = nil; + for (int i = 0; i < [_rowAssets count]; ++i) { + + ELCAsset *asset = [_rowAssets objectAtIndex:i]; - ELCAsset *asset = [_rowAssets objectAtIndex:i]; + if (i < [_imageViewArray count]) { + UIImageView *imageView = [_imageViewArray objectAtIndex:i]; + imageView.image = [UIImage imageWithCGImage:((ALAsset*)asset.asset).thumbnail]; + } else { + UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageWithCGImage:((ALAsset*)asset.asset).thumbnail]]; + [_imageViewArray addObject:imageView]; + } + + if (i < [_overlayViewArray count]) { + ELCOverlayImageView *overlayView = [_overlayViewArray objectAtIndex:i]; + overlayView.hidden = asset.selected ? NO : YES; + overlayView.labIndex.text = [NSString stringWithFormat:@"%d", asset.index + 1]; + } else { + if (overlayImage == nil) { + overlayImage = [UIImage imageNamed:@"Overlay.png"]; + } + ELCOverlayImageView *overlayView = [[ELCOverlayImageView alloc] initWithImage:overlayImage]; + [_overlayViewArray addObject:overlayView]; + overlayView.hidden = asset.selected ? NO : YES; + overlayView.labIndex.text = [NSString stringWithFormat:@"%d", asset.index + 1]; + } - if (i < [_imageViewArray count]) { - UIImageView *imageView = [_imageViewArray objectAtIndex:i]; - imageView.image = [UIImage imageWithCGImage:asset.asset.thumbnail]; - } else { - UIImageView *imageView = [[UIImageView alloc] initWithImage:[UIImage imageWithCGImage:asset.asset.thumbnail]]; - [_imageViewArray addObject:imageView]; } - - if (i < [_overlayViewArray count]) { - ELCOverlayImageView *overlayView = [_overlayViewArray objectAtIndex:i]; - overlayView.hidden = asset.selected ? NO : YES; - overlayView.labIndex.text = [NSString stringWithFormat:@"%d", asset.index + 1]; - } else { - if (overlayImage == nil) { - overlayImage = [UIImage imageNamed:@"Overlay.png"]; + } else { + + UIImage *overlayImage = nil; + for (int i = 0; i < [_rowAssets count]; ++i) { + + ELCAsset *asset = [_rowAssets objectAtIndex:i]; + + PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init]; + + // Download from cloud if necessary + // Need to make NO for existing images. + options.networkAccessAllowed = YES; + options.progressHandler = ^(double progress, NSError *error, BOOL *stop, NSDictionary *info) { + + }; + + if (i < [_imageViewArray count]) { + UIImageView *imageView = [_imageViewArray objectAtIndex:i]; + PHAsset *phAsset = (PHAsset *)asset.asset; + [self.imageManager requestImageForAsset:phAsset targetSize:CGSizeMake(70, 70) contentMode:PHImageContentModeAspectFill options:options resultHandler:^(UIImage * result, NSDictionary * info) { + imageView.image = result; + }]; + + } else { + UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 70, 70)]; + PHAsset *phAsset = (PHAsset *)asset.asset; + [self.imageManager requestImageForAsset:phAsset targetSize:CGSizeMake(70, 70) contentMode:PHImageContentModeAspectFill options:options resultHandler:^(UIImage * result, NSDictionary * info) { + imageView.image = result; + }]; + + [_imageViewArray addObject:imageView]; + } + + if (i < [_overlayViewArray count]) { + ELCOverlayImageView *overlayView = [_overlayViewArray objectAtIndex:i]; + overlayView.hidden = asset.selected ? NO : YES; + overlayView.labIndex.text = [NSString stringWithFormat:@"%d", asset.index + 1]; + } else { + if (overlayImage == nil) { + overlayImage = [UIImage imageNamed:@"Overlay.png"]; + } + ELCOverlayImageView *overlayView = [[ELCOverlayImageView alloc] initWithImage:overlayImage]; + [_overlayViewArray addObject:overlayView]; + overlayView.hidden = asset.selected ? NO : YES; + overlayView.labIndex.text = [NSString stringWithFormat:@"%d", asset.index + 1]; } - ELCOverlayImageView *overlayView = [[ELCOverlayImageView alloc] initWithImage:overlayImage]; - [_overlayViewArray addObject:overlayView]; - overlayView.hidden = asset.selected ? NO : YES; - overlayView.labIndex.text = [NSString stringWithFormat:@"%d", asset.index + 1]; } + } } diff --git a/Classes/ELCImagePicker/ELCAssetTablePicker.h b/Classes/ELCImagePicker/ELCAssetTablePicker.h index 8148ef6..5284321 100755 --- a/Classes/ELCImagePicker/ELCAssetTablePicker.h +++ b/Classes/ELCImagePicker/ELCAssetTablePicker.h @@ -14,7 +14,7 @@ @interface ELCAssetTablePicker : UITableViewController @property (nonatomic, weak) id parent; -@property (nonatomic, strong) ALAssetsGroup *assetGroup; +@property (nonatomic, strong) NSObject *assetGroup; @property (nonatomic, strong) NSMutableArray *elcAssets; @property (nonatomic, strong) IBOutlet UILabel *selectedAssetsLabel; @property (nonatomic, assign) BOOL singleSelection; diff --git a/Classes/ELCImagePicker/ELCAssetTablePicker.m b/Classes/ELCImagePicker/ELCAssetTablePicker.m index 24830be..6d9b248 100755 --- a/Classes/ELCImagePicker/ELCAssetTablePicker.m +++ b/Classes/ELCImagePicker/ELCAssetTablePicker.m @@ -10,10 +10,15 @@ #import "ELCAsset.h" #import "ELCAlbumPickerController.h" #import "ELCConsole.h" +#import "ELCConstants.h" +#import -@interface ELCAssetTablePicker () + +@interface ELCAssetTablePicker () @property (nonatomic, assign) int columns; +@property (strong, nonatomic) id synchronizationObject; +@property (assign, nonatomic, getter=isProcessing) BOOL processing; @end @@ -47,24 +52,36 @@ - (void)viewDidLoad [self.navigationItem setRightBarButtonItem:doneButtonItem]; [self.navigationItem setTitle:NSLocalizedString(@"Loading...", nil)]; } - - [self performSelectorInBackground:@selector(preparePhotos) withObject:nil]; // Register for notifications when the photo library has changed - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(preparePhotos) name:ALAssetsLibraryChangedNotification object:nil]; + if(!IS_IOS8){ + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(preparePhotos) name:ALAssetsLibraryChangedNotification object:nil]; + }else { + [[PHPhotoLibrary sharedPhotoLibrary] registerChangeObserver:self]; + } + + [self performSelectorInBackground:@selector(preparePhotos) withObject:nil]; } - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; + [[ELCConsole mainConsole] removeAllIndex]; self.columns = self.view.bounds.size.width / 80; + [self performSelectorInBackground:@selector(processPhotos) withObject:nil]; } - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; [[ELCConsole mainConsole] removeAllIndex]; - [[NSNotificationCenter defaultCenter] removeObserver:self name:ALAssetsLibraryChangedNotification object:nil]; + + if (!IS_IOS8) { + [[NSNotificationCenter defaultCenter] removeObserver:self name:ALAssetsLibraryChangedNotification object:nil]; + }else { + [[PHPhotoLibrary sharedPhotoLibrary] unregisterChangeObserver:self]; + } + } - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation @@ -81,46 +98,108 @@ - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceO - (void)preparePhotos { + [self performSelectorInBackground:@selector(processPhotos) withObject:nil]; +} + +- (void)processPhotos +{ + @synchronized(self.synchronizationObject) { + if (self.processing) { + return; + } + self.processing = YES; + } + @autoreleasepool { - [self.elcAssets removeAllObjects]; - [self.assetGroup enumerateAssetsUsingBlock:^(ALAsset *result, NSUInteger index, BOOL *stop) { - - if (result == nil) { - return; - } - - ELCAsset *elcAsset = [[ELCAsset alloc] initWithAsset:result]; - [elcAsset setParent:self]; - - BOOL isAssetFiltered = NO; - if (self.assetPickerFilterDelegate && - [self.assetPickerFilterDelegate respondsToSelector:@selector(assetTablePicker:isAssetFilteredOut:)]) - { - isAssetFiltered = [self.assetPickerFilterDelegate assetTablePicker:self isAssetFilteredOut:(ELCAsset*)elcAsset]; + [[ELCConsole mainConsole] removeAllIndex]; + if (!IS_IOS8) { + NSEnumerationOptions options = NSEnumerationReverse; + if ([[ELCConsole mainConsole] sortImagesAscendingByDates]) { + options = 0; } + [((ALAssetsGroup *)self.assetGroup) enumerateAssetsWithOptions:options + usingBlock:^(ALAsset *result, NSUInteger index, BOOL *stop) { + + if (result == nil) { + @synchronized(self.synchronizationObject) { + self.processing = NO; + } + return; + } + + ELCAsset *elcAsset = [[ELCAsset alloc] initWithAsset:result]; + [elcAsset setParent:self]; + + BOOL isAssetFiltered = NO; + if (self.assetPickerFilterDelegate && + [self.assetPickerFilterDelegate respondsToSelector:@selector(assetTablePicker:isAssetFilteredOut:)]) + { + isAssetFiltered = [self.assetPickerFilterDelegate assetTablePicker:self isAssetFilteredOut:(ELCAsset*)elcAsset]; + } - if (!isAssetFiltered) { - [self.elcAssets addObject:elcAsset]; + if (!isAssetFiltered) { + [self.elcAssets addObject:elcAsset]; + } + + }]; + + dispatch_sync(dispatch_get_main_queue(), ^{ + [self.tableView reloadData]; +// // scroll to bottom +// long section = [self numberOfSectionsInTableView:self.tableView] - 1; +// long row = [self tableView:self.tableView numberOfRowsInSection:section] - 1; +// if (section >= 0 && row >= 0) { +// NSIndexPath *ip = [NSIndexPath indexPathForRow:row +// inSection:section]; +// [self.tableView scrollToRowAtIndexPath:ip +// atScrollPosition:UITableViewScrollPositionBottom +// animated:NO]; +// } + + [self.navigationItem setTitle:self.singleSelection ? NSLocalizedString(@"Pick Photo", nil) : NSLocalizedString(@"Pick Photos", nil)]; + }); + }else { + PHFetchResult *tempFetchResult = (PHFetchResult *)self.assetGroup; + for (int k =0; k < tempFetchResult.count; k++) { + PHAsset *asset = tempFetchResult[k]; + ELCAsset *elcAsset = [[ELCAsset alloc] initWithAsset:asset]; + [elcAsset setParent:self]; + + BOOL isAssetFiltered = NO; + if (self.assetPickerFilterDelegate && + [self.assetPickerFilterDelegate respondsToSelector:@selector(assetTablePicker:isAssetFilteredOut:)]) + { + isAssetFiltered = [self.assetPickerFilterDelegate assetTablePicker:self isAssetFilteredOut:(ELCAsset*)elcAsset]; + } + + if (!isAssetFiltered) { + [self.elcAssets addObject:elcAsset]; + } } + - }]; - - dispatch_sync(dispatch_get_main_queue(), ^{ - [self.tableView reloadData]; - // scroll to bottom - long section = [self numberOfSectionsInTableView:self.tableView] - 1; - long row = [self tableView:self.tableView numberOfRowsInSection:section] - 1; - if (section >= 0 && row >= 0) { - NSIndexPath *ip = [NSIndexPath indexPathForRow:row - inSection:section]; - [self.tableView scrollToRowAtIndexPath:ip - atScrollPosition:UITableViewScrollPositionBottom - animated:NO]; + @synchronized(self.synchronizationObject) { + self.processing = NO; } - [self.navigationItem setTitle:self.singleSelection ? NSLocalizedString(@"Pick Photo", nil) : NSLocalizedString(@"Pick Photos", nil)]; - }); + + dispatch_sync(dispatch_get_main_queue(), ^{ + [self.tableView reloadData]; + // scroll to bottom +// long section = [self numberOfSectionsInTableView:self.tableView] - 1; +// long row = [self tableView:self.tableView numberOfRowsInSection:section] - 1; +// if (section >= 0 && row >= 0) { +// NSIndexPath *ip = [NSIndexPath indexPathForRow:row +// inSection:section]; +// [self.tableView scrollToRowAtIndexPath:ip +// atScrollPosition:UITableViewScrollPositionBottom +// animated:NO]; +// } + + [self.navigationItem setTitle:self.singleSelection ? NSLocalizedString(@"Pick Photo", nil) : NSLocalizedString(@"Pick Photos", nil)]; + }); + } } } @@ -231,9 +310,7 @@ - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - if (self.columns <= 0) { //Sometimes called before we know how many columns we have - self.columns = 4; - } + NSInteger numRows = ceil([self.elcAssets count] / (float)self.columns); return numRows; } @@ -242,7 +319,11 @@ - (NSArray *)assetsForIndexPath:(NSIndexPath *)path { long index = path.row * self.columns; long length = MIN(self.columns, [self.elcAssets count] - index); - return [self.elcAssets subarrayWithRange:NSMakeRange(index, length)]; + NSRange subarrayRange = NSMakeRange(index, length); + if (NSMaxRange(subarrayRange) > self.elcAssets.count) { + return nil; + } + return [self.elcAssets subarrayWithRange:subarrayRange]; } // Customize the appearance of table view cells. @@ -279,5 +360,27 @@ - (int)totalSelectedAssets return count; } +#pragma mark - Photo Library Observer + +-(void)photoLibraryDidChange:(PHChange *)changeInstance { + PHFetchResultChangeDetails *changeDetails = [changeInstance changeDetailsForFetchResult:(PHFetchResult*)self.assetGroup]; + + if(changeDetails) { + self.assetGroup = [changeDetails fetchResultAfterChanges]; + [self preparePhotos]; + } +} + +#pragma mark - Property - + +#pragma mark Lazy loading + +- (id)synchronizationObject { + if (_synchronizationObject == nil) { + _synchronizationObject = [NSObject new]; + } + return _synchronizationObject; +} + @end diff --git a/Classes/ELCImagePicker/ELCConsole.h b/Classes/ELCImagePicker/ELCConsole.h index eda755e..25138dd 100644 --- a/Classes/ELCImagePicker/ELCConsole.h +++ b/Classes/ELCImagePicker/ELCConsole.h @@ -13,6 +13,7 @@ NSMutableArray *myIndex; } @property (nonatomic,assign) BOOL onOrder; +@property (nonatomic, assign) BOOL sortImagesAscendingByDates; + (ELCConsole *)mainConsole; - (void)addIndex:(int)index; - (void)removeIndex:(int)index; diff --git a/Classes/ELCImagePicker/ELCConsole.m b/Classes/ELCImagePicker/ELCConsole.m index cc6e700..3db22e2 100644 --- a/Classes/ELCImagePicker/ELCConsole.m +++ b/Classes/ELCImagePicker/ELCConsole.m @@ -66,7 +66,7 @@ - (int)currIndex - (int)numOfSelectedElements { - return [myIndex count]; + return (int)[myIndex count]; } @end diff --git a/Classes/ELCImagePicker/ELCConstants.h b/Classes/ELCImagePicker/ELCConstants.h new file mode 100644 index 0000000..9e31d64 --- /dev/null +++ b/Classes/ELCImagePicker/ELCConstants.h @@ -0,0 +1,15 @@ +// +// ELCConstants.h +// ELCImagePickerDemo +// +// Created by synerzip on 08/10/15. +// Copyright © 2015 ELC Technologies. All rights reserved. +// + +#ifndef ELCConstants_h +#define ELCConstants_h + +#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending) +#define IS_IOS8 SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"8.0") + +#endif /* ELCConstants_h */ diff --git a/Classes/ELCImagePicker/ELCImagePickerController.h b/Classes/ELCImagePicker/ELCImagePickerController.h index 53d90af..03a1248 100755 --- a/Classes/ELCImagePicker/ELCImagePickerController.h +++ b/Classes/ELCImagePicker/ELCImagePickerController.h @@ -35,6 +35,7 @@ @property (nonatomic, weak) id imagePickerDelegate; @property (nonatomic, assign) NSInteger maximumImagesCount; @property (nonatomic, assign) BOOL onOrder; +@property (nonatomic, assign) BOOL sortImagesAscendingByDates; /** * An array indicating the media types to be accessed by the media picker controller. * Same usage as for UIImagePickerController. diff --git a/Classes/ELCImagePicker/ELCImagePickerController.m b/Classes/ELCImagePicker/ELCImagePickerController.m index b7f3eda..cf9c4ac 100755 --- a/Classes/ELCImagePicker/ELCImagePickerController.m +++ b/Classes/ELCImagePicker/ELCImagePickerController.m @@ -14,9 +14,34 @@ #import #import #import "ELCConsole.h" +#import "ELCConstants.h" +#import @implementation ELCImagePickerController +#pragma mark - property - + +- (BOOL)onOrder +{ + return [[ELCConsole mainConsole] onOrder]; +} + +- (void)setOnOrder:(BOOL)onOrder +{ + [[ELCConsole mainConsole] setOnOrder:onOrder]; +} + +- (BOOL)sortImagesAscendingByDates { + BOOL result = [[ELCConsole mainConsole] sortImagesAscendingByDates]; + return result; +} + +- (void)setSortImagesAscendingByDates:(BOOL)sortImagesAscendingByDates { + [[ELCConsole mainConsole] setSortImagesAscendingByDates:sortImagesAscendingByDates]; +} + +#pragma mark - life cycle - + //Using auto synthesizers - (id)initImagePicker @@ -90,50 +115,60 @@ - (BOOL)shouldDeselectAsset:(ELCAsset *)asset previousCount:(NSUInteger)previous - (void)selectedAssets:(NSArray *)assets { NSMutableArray *returnArray = [[NSMutableArray alloc] init]; - - for(ELCAsset *elcasset in assets) { - ALAsset *asset = elcasset.asset; - id obj = [asset valueForProperty:ALAssetPropertyType]; - if (!obj) { - continue; - } - NSMutableDictionary *workingDictionary = [[NSMutableDictionary alloc] init]; - - CLLocation* wgs84Location = [asset valueForProperty:ALAssetPropertyLocation]; - if (wgs84Location) { - [workingDictionary setObject:wgs84Location forKey:ALAssetPropertyLocation]; - } - - [workingDictionary setObject:obj forKey:UIImagePickerControllerMediaType]; - - //This method returns nil for assets from a shared photo stream that are not yet available locally. If the asset becomes available in the future, an ALAssetsLibraryChangedNotification notification is posted. - ALAssetRepresentation *assetRep = [asset defaultRepresentation]; - - if(assetRep != nil) { - if (_returnsImage) { - CGImageRef imgRef = nil; - //defaultRepresentation returns image as it appears in photo picker, rotated and sized, - //so use UIImageOrientationUp when creating our image below. - UIImageOrientation orientation = UIImageOrientationUp; + if(!IS_IOS8) { + for(ELCAsset *elcasset in assets) { + ALAsset *asset = (ALAsset*)elcasset.asset; + id obj = [asset valueForProperty:ALAssetPropertyType]; + if (!obj) { + continue; + } + NSMutableDictionary *workingDictionary = [[NSMutableDictionary alloc] init]; - if (_returnsOriginalImage) { - imgRef = [assetRep fullResolutionImage]; - orientation = [assetRep orientation]; - } else { - imgRef = [assetRep fullScreenImage]; - } - UIImage *img = [UIImage imageWithCGImage:imgRef - scale:1.0f - orientation:orientation]; - [workingDictionary setObject:img forKey:UIImagePickerControllerOriginalImage]; + CLLocation* wgs84Location = [asset valueForProperty:ALAssetPropertyLocation]; + if (wgs84Location) { + [workingDictionary setObject:wgs84Location forKey:ALAssetPropertyLocation]; } + + [workingDictionary setObject:obj forKey:UIImagePickerControllerMediaType]; + + //This method returns nil for assets from a shared photo stream that are not yet available locally. If the asset becomes available in the future, an ALAssetsLibraryChangedNotification notification is posted. + ALAssetRepresentation *assetRep = [asset defaultRepresentation]; + + if(assetRep != nil) { + if (_returnsImage) { + CGImageRef imgRef = nil; + //defaultRepresentation returns image as it appears in photo picker, rotated and sized, + //so use UIImageOrientationUp when creating our image below. + UIImageOrientation orientation = UIImageOrientationUp; + + if (_returnsOriginalImage) { + imgRef = [assetRep fullResolutionImage]; + + NSNumber *orientationValue = [asset valueForProperty:@"ALAssetPropertyOrientation"]; + if (orientationValue != nil) { + orientation = [orientationValue intValue]; + } + + } else { + imgRef = [assetRep fullScreenImage]; + } + UIImage *img = [UIImage imageWithCGImage:imgRef + scale:1.0f + orientation:orientation]; + [workingDictionary setObject:img forKey:UIImagePickerControllerOriginalImage]; + } - [workingDictionary setObject:[[asset valueForProperty:ALAssetPropertyURLs] valueForKey:[[[asset valueForProperty:ALAssetPropertyURLs] allKeys] objectAtIndex:0]] forKey:UIImagePickerControllerReferenceURL]; + [workingDictionary setObject:[[asset valueForProperty:ALAssetPropertyURLs] valueForKey:[[[asset valueForProperty:ALAssetPropertyURLs] allKeys] objectAtIndex:0]] forKey:UIImagePickerControllerReferenceURL]; + + [returnArray addObject:workingDictionary]; + } - [returnArray addObject:workingDictionary]; } - - } + }else { + for(ELCAsset *elcasset in assets) { + [returnArray addObject:elcasset.asset]; + } + } if (_imagePickerDelegate != nil && [_imagePickerDelegate respondsToSelector:@selector(elcImagePickerController:didFinishPickingMediaWithInfo:)]) { [_imagePickerDelegate performSelector:@selector(elcImagePickerController:didFinishPickingMediaWithInfo:) withObject:self withObject:returnArray]; } else { @@ -150,14 +185,4 @@ - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfa } } -- (BOOL)onOrder -{ - return [[ELCConsole mainConsole] onOrder]; -} - -- (void)setOnOrder:(BOOL)onOrder -{ - [[ELCConsole mainConsole] setOnOrder:onOrder]; -} - @end diff --git a/Classes/ELCImagePickerDemoViewController.m b/Classes/ELCImagePickerDemoViewController.m index 0b53ef2..887a248 100644 --- a/Classes/ELCImagePickerDemoViewController.m +++ b/Classes/ELCImagePickerDemoViewController.m @@ -9,6 +9,8 @@ #import "ELCImagePickerDemoAppDelegate.h" #import "ELCImagePickerDemoViewController.h" #import +#import +#import "ELCConstants.h" @interface ELCImagePickerDemoViewController () @@ -38,28 +40,41 @@ - (IBAction)launchController - (IBAction)launchSpecialController { - ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init]; - self.specialLibrary = library; - NSMutableArray *groups = [NSMutableArray array]; - [_specialLibrary enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos usingBlock:^(ALAssetsGroup *group, BOOL *stop) { - if (group) { - [groups addObject:group]; - } else { - // this is the end - [self displayPickerForGroup:[groups objectAtIndex:0]]; - } - } failureBlock:^(NSError *error) { - self.chosenImages = nil; - UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Error" message:[NSString stringWithFormat:@"Album Error: %@ - %@", [error localizedDescription], [error localizedRecoverySuggestion]] delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil]; - [alert show]; + //add photo framework for ios 8 and above + + if(!IS_IOS8_OR_LATER) { + ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init]; + self.specialLibrary = library; + NSMutableArray *groups = [NSMutableArray array]; + [_specialLibrary enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos usingBlock:^(ALAssetsGroup *group, BOOL *stop) { + if (group) { + [groups addObject:group]; + } else { + // this is the end + [self displayPickerForGroup:[groups objectAtIndex:0]]; + } + } failureBlock:^(NSError *error) { + self.chosenImages = nil; + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:@"Error" message:[NSString stringWithFormat:@"Album Error: %@ - %@", [error localizedDescription], [error localizedRecoverySuggestion]] delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil]; + [alert show]; + + NSLog(@"A problem occured %@", [error description]); + // an error here means that the asset groups were inaccessable. + // Maybe the user or system preferences refused access. + }]; + }else { + //Get All Saved Photos + //Fetch PHAssetCollections: + PHFetchOptions *options = [[PHFetchOptions alloc] init]; + options.predicate = [NSPredicate predicateWithFormat:@"mediaType in %@", @[@(PHAssetMediaTypeImage)]]; + options.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:NO]]; + PHFetchResult *assetsFetchResult = [PHAsset fetchAssetsWithOptions:options]; - NSLog(@"A problem occured %@", [error description]); - // an error here means that the asset groups were inaccessable. - // Maybe the user or system preferences refused access. - }]; + [self displayPickerForGroup:assetsFetchResult]; + } } -- (void)displayPickerForGroup:(ALAssetsGroup *)group +- (void)displayPickerForGroup:(NSObject *)group { ELCAssetTablePicker *tablePicker = [[ELCAssetTablePicker alloc] initWithStyle:UITableViewStylePlain]; tablePicker.singleSelection = YES; @@ -75,7 +90,9 @@ - (void)displayPickerForGroup:(ALAssetsGroup *)group // Move me tablePicker.assetGroup = group; - [tablePicker.assetGroup setAssetsFilter:[ALAssetsFilter allAssets]]; + if (!IS_IOS8_OR_LATER) { + [((ALAssetsGroup*)tablePicker.assetGroup) setAssetsFilter:[ALAssetsFilter allAssets]]; + } [self presentViewController:elcPicker animated:YES completion:nil]; } @@ -103,41 +120,83 @@ - (void)elcImagePickerController:(ELCImagePickerController *)picker didFinishPic workingFrame.origin.x = 0; NSMutableArray *images = [NSMutableArray arrayWithCapacity:[info count]]; - for (NSDictionary *dict in info) { - if ([dict objectForKey:UIImagePickerControllerMediaType] == ALAssetTypePhoto){ - if ([dict objectForKey:UIImagePickerControllerOriginalImage]){ - UIImage* image=[dict objectForKey:UIImagePickerControllerOriginalImage]; - [images addObject:image]; + if(!IS_IOS8_OR_LATER) { + for (NSDictionary *dict in info) { + if ([dict objectForKey:UIImagePickerControllerMediaType] == ALAssetTypePhoto){ + if ([dict objectForKey:UIImagePickerControllerOriginalImage]){ + UIImage* image=[dict objectForKey:UIImagePickerControllerOriginalImage]; + [images addObject:image]; + + UIImageView *imageview = [[UIImageView alloc] initWithImage:image]; + [imageview setContentMode:UIViewContentModeScaleAspectFit]; + imageview.frame = workingFrame; + + [_scrollView addSubview:imageview]; + + workingFrame.origin.x = workingFrame.origin.x + workingFrame.size.width; + } else { + NSLog(@"UIImagePickerControllerReferenceURL = %@", dict); + } + } else if ([dict objectForKey:UIImagePickerControllerMediaType] == ALAssetTypeVideo){ + if ([dict objectForKey:UIImagePickerControllerOriginalImage]){ + UIImage* image=[dict objectForKey:UIImagePickerControllerOriginalImage]; + + [images addObject:image]; + + UIImageView *imageview = [[UIImageView alloc] initWithImage:image]; + [imageview setContentMode:UIViewContentModeScaleAspectFit]; + imageview.frame = workingFrame; + + [_scrollView addSubview:imageview]; + + workingFrame.origin.x = workingFrame.origin.x + workingFrame.size.width; + } else { + NSLog(@"UIImagePickerControllerReferenceURL = %@", dict); + } + } else { + NSLog(@"Uknown asset type"); + } + } + }else { + for (PHAsset *asset in info) { + + + + if (asset.mediaType == PHAssetMediaTypeImage){ - UIImageView *imageview = [[UIImageView alloc] initWithImage:image]; + UIImageView *imageview = [[UIImageView alloc] init]; [imageview setContentMode:UIViewContentModeScaleAspectFit]; imageview.frame = workingFrame; - [_scrollView addSubview:imageview]; - workingFrame.origin.x = workingFrame.origin.x + workingFrame.size.width; - } else { - NSLog(@"UIImagePickerControllerReferenceURL = %@", dict); - } - } else if ([dict objectForKey:UIImagePickerControllerMediaType] == ALAssetTypeVideo){ - if ([dict objectForKey:UIImagePickerControllerOriginalImage]){ - UIImage* image=[dict objectForKey:UIImagePickerControllerOriginalImage]; - - [images addObject:image]; + PHImageRequestOptions *options = [[PHImageRequestOptions alloc] init]; + + // Download from cloud if necessary + options.networkAccessAllowed = YES; + options.progressHandler = ^(double progress, NSError *error, BOOL *stop, NSDictionary *info) { + dispatch_async(dispatch_get_main_queue(), ^{ + //you can update progress here + }); + }; + + + [[PHImageManager defaultManager] requestImageForAsset:asset targetSize:workingFrame.size contentMode:PHImageContentModeAspectFit options:options resultHandler:^(UIImage *result, NSDictionary *info) { + if (result) { + imageview.image = result; + [images addObject:result]; + } + }]; + - UIImageView *imageview = [[UIImageView alloc] initWithImage:image]; - [imageview setContentMode:UIViewContentModeScaleAspectFit]; - imageview.frame = workingFrame; [_scrollView addSubview:imageview]; workingFrame.origin.x = workingFrame.origin.x + workingFrame.size.width; } else { - NSLog(@"UIImagePickerControllerReferenceURL = %@", dict); + } - } else { - NSLog(@"Uknown asset type"); } + } self.chosenImages = images; diff --git a/ELCImagePickerController.podspec b/ELCImagePickerController.podspec index 89e3c3a..360c3e2 100644 --- a/ELCImagePickerController.podspec +++ b/ELCImagePickerController.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'ELCImagePickerController' - s.version = '0.2.0' + s.version = '0.2.1' s.summary = 'A Multiple Selection Image Picker.' s.homepage = 'https://github.com/elc/ELCImagePickerController' s.license = { @@ -9,11 +9,11 @@ Pod::Spec.new do |s| } s.author = {'ELC Technologies' => 'http://elctech.com'} s.source = {:git => 'https://github.com/elc/ELCImagePickerController.git', - :tag => '0.2.0' + :tag => '0.2.1' } - s.platform = :ios, '6.0' + s.platform = :ios, '7.0' s.resources = 'Classes/**/*.{xib,png}' s.source_files = 'Classes/ELCImagePicker/*.{h,m}' - s.framework = 'Foundation', 'UIKit', 'AssetsLibrary', 'CoreLocation' + s.framework = 'Foundation', 'UIKit', 'AssetsLibrary', 'CoreLocation', 'Photos' s.requires_arc = true end diff --git a/ELCImagePickerDemo-Info.plist b/ELCImagePickerDemo-Info.plist index 5a79e77..a100800 100644 --- a/ELCImagePickerDemo-Info.plist +++ b/ELCImagePickerDemo-Info.plist @@ -29,7 +29,7 @@ CFBundleIdentifier - com.burnsidedigital.elcimagepickerdemo + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName diff --git a/ELCImagePickerDemo.xcodeproj/project.pbxproj b/ELCImagePickerDemo.xcodeproj/project.pbxproj index eeecc92..4b45425 100755 --- a/ELCImagePickerDemo.xcodeproj/project.pbxproj +++ b/ELCImagePickerDemo.xcodeproj/project.pbxproj @@ -25,6 +25,7 @@ 28AD733F0D9D9553002E5188 /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 28AD733E0D9D9553002E5188 /* MainWindow.xib */; }; 28D7ACF80DDB3853001CB0EB /* ELCImagePickerDemoViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 28D7ACF70DDB3853001CB0EB /* ELCImagePickerDemoViewController.m */; }; 4AAFDA62194840F20020FCC4 /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 4AAFDA61194840F20020FCC4 /* MobileCoreServices.framework */; }; + 7E1BA03D1BCD23F7004D158B /* Photos.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7E1BA03C1BCD23F7004D158B /* Photos.framework */; }; 83C6BC9714476B280064D71D /* elc-ios-icon@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 83C6BC9514476B280064D71D /* elc-ios-icon@2x.png */; }; 83C6BC9814476B280064D71D /* elc-ios-icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 83C6BC9614476B280064D71D /* elc-ios-icon.png */; }; E29A5E3C1239C42A008BB149 /* AssetsLibrary.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E29A5E3B1239C42A008BB149 /* AssetsLibrary.framework */; }; @@ -62,6 +63,8 @@ 32CA4F630368D1EE00C91783 /* ELCImagePickerDemo_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ELCImagePickerDemo_Prefix.pch; sourceTree = ""; }; 4AAFDA61194840F20020FCC4 /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = System/Library/Frameworks/MobileCoreServices.framework; sourceTree = SDKROOT; }; 5FAEB088190A3FA9002D73C4 /* ELCImagePickerHeader.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ELCImagePickerHeader.h; sourceTree = ""; }; + 7E1BA03B1BCD2379004D158B /* ELCConstants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ELCConstants.h; path = "../../../HipPocket/hippocket-ios/NonPods/ELCImagePicker/ELCConstants.h"; sourceTree = ""; }; + 7E1BA03C1BCD23F7004D158B /* Photos.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Photos.framework; path = System/Library/Frameworks/Photos.framework; sourceTree = SDKROOT; }; 83C6BC9514476B280064D71D /* elc-ios-icon@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "elc-ios-icon@2x.png"; sourceTree = ""; }; 83C6BC9614476B280064D71D /* elc-ios-icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "elc-ios-icon.png"; sourceTree = ""; }; 8D1107310486CEB800E47090 /* ELCImagePickerDemo-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "ELCImagePickerDemo-Info.plist"; plistStructureDefinitionIdentifier = "com.apple.xcode.plist.structure-definition.iphone.info-plist"; sourceTree = ""; }; @@ -78,6 +81,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( + 7E1BA03D1BCD23F7004D158B /* Photos.framework in Frameworks */, 4AAFDA62194840F20020FCC4 /* MobileCoreServices.framework in Frameworks */, 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */, 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */, @@ -157,6 +161,7 @@ 29B97323FDCFA39411CA2CEA /* Frameworks */ = { isa = PBXGroup; children = ( + 7E1BA03C1BCD23F7004D158B /* Photos.framework */, 4AAFDA61194840F20020FCC4 /* MobileCoreServices.framework */, E29A5E3B1239C42A008BB149 /* AssetsLibrary.framework */, 288765A40DF7441C002DB57D /* CoreGraphics.framework */, @@ -169,6 +174,7 @@ 4252A0981593013500086D05 /* ELCImagePicker */ = { isa = PBXGroup; children = ( + 7E1BA03B1BCD2379004D158B /* ELCConstants.h */, 1A2C0FFD17026CF0004FAFA0 /* ELCAlbumPickerController.h */, 1A2C0FFE17026CF0004FAFA0 /* ELCAlbumPickerController.m */, 1A2C0FFF17026CF0004FAFA0 /* ELCAsset.h */, @@ -216,7 +222,7 @@ 29B97313FDCFA39411CA2CEA /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0510; + LastUpgradeCheck = 0700; ORGANIZATIONNAME = "ELC Technologies"; }; buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "ELCImagePickerDemo" */; @@ -283,7 +289,7 @@ ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ENABLE_OBJC_ARC = YES; CODE_SIGN_IDENTITY = ""; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = ""; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; GCC_DYNAMIC_NO_PIC = NO; GCC_OPTIMIZATION_LEVEL = 0; @@ -291,6 +297,7 @@ GCC_PREFIX_HEADER = ELCImagePickerDemo_Prefix.pch; INFOPLIST_FILE = "ELCImagePickerDemo-Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 6.0; + PRODUCT_BUNDLE_IDENTIFIER = com.burnsidedigital.elcimagepickerdemo; PRODUCT_NAME = ELCImagePickerDemo; PROVISIONING_PROFILE = ""; "PROVISIONING_PROFILE[sdk=iphoneos*]" = ""; @@ -303,12 +310,13 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ENABLE_OBJC_ARC = YES; - CODE_SIGN_IDENTITY = "iPhone Developer"; + CODE_SIGN_IDENTITY = ""; COPY_PHASE_STRIP = YES; GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PREFIX_HEADER = ELCImagePickerDemo_Prefix.pch; INFOPLIST_FILE = "ELCImagePickerDemo-Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 6.0; + PRODUCT_BUNDLE_IDENTIFIER = com.burnsidedigital.elcimagepickerdemo; PRODUCT_NAME = ELCImagePickerDemo; PROVISIONING_PROFILE = ""; TARGETED_DEVICE_FAMILY = "1,2"; @@ -320,6 +328,7 @@ isa = XCBuildConfiguration; buildSettings = { "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = c99; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; diff --git a/README.md b/README.md index a0d9dfb..4ce6534 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ -# ELCImagePickerController +# ELCImagePickerController with Photos Library and iCloud sync support -*A clone of the UIImagePickerController using the Assets Library Framework allowing for multiple asset selection.* +*A clone of the UIImagePickerController using Assets Library Framework allowing for multiple asset selection.* +*Updated for the Photos Library to support iCloud sync from iOS 8 onwards.* ## Usage @@ -22,7 +23,7 @@ elcPicker.imagePickerDelegate = self; [elcPicker release]; ``` -The `ELCImagePickerController` will return the select images back to the `ELCImagePickerControllerDelegate`. The delegate contains methods very similar to the `UIImagePickerControllerDelegate`. Instead of returning one dictionary representing a single image the controller sends back an array of similarly structured dictionaries. The two delegate methods are: +The `ELCImagePickerController` will return the select images back to the `ELCImagePickerControllerDelegate`. The delegate contains methods very similar to the `UIImagePickerControllerDelegate`. Instead of returning one dictionary representing a single image the controller sends back an array of PHAsset for iOS 8, 9 and similarly structured dictionaries for iOS 7,6. The two delegate methods are: ```obj-c - (void)elcImagePickerController:(ELCImagePickerController *)picker didFinishPickingMediaWithInfo:(NSArray *)info;