diff --git a/Classes/ELCImagePicker/ELCAlbumPickerController.h b/Classes/ELCImagePicker/ELCAlbumPickerController.h index 1c41414..15e07fc 100755 --- a/Classes/ELCImagePicker/ELCAlbumPickerController.h +++ b/Classes/ELCImagePicker/ELCAlbumPickerController.h @@ -15,6 +15,7 @@ @property (nonatomic, weak) id parent; @property (nonatomic, strong) NSMutableArray *assetGroups; @property (nonatomic, strong) NSArray *mediaTypes; +@property (strong, nonatomic) ELCAssetTablePicker *picker; // optional, can be used to filter the assets displayed @property (nonatomic, weak) id assetPickerFilterDelegate; diff --git a/Classes/ELCImagePicker/ELCAlbumPickerController.m b/Classes/ELCImagePicker/ELCAlbumPickerController.m index 8058622..c3df86f 100755 --- a/Classes/ELCImagePicker/ELCAlbumPickerController.m +++ b/Classes/ELCImagePicker/ELCAlbumPickerController.m @@ -13,6 +13,8 @@ @interface ELCAlbumPickerController () @property (nonatomic, strong) ALAssetsLibrary *library; +@property (nonatomic, strong) NSString *loadedGroupID; +@property (nonatomic, strong) NSMutableArray *tempAssetGroups; @end @@ -37,68 +39,193 @@ - (void)viewDidLoad ALAssetsLibrary *assetLibrary = [[ALAssetsLibrary alloc] init]; self.library = assetLibrary; - + // 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; - } - - // 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]; - }; - - // Group Enumerator Failure Block - void (^assetGroupEnumberatorFailure)(NSError *) = ^(NSError *error) { - - UIAlertView * alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Error", nil) message:[NSString stringWithFormat:@"Album Error: %@ - %@", [error localizedDescription], [error localizedRecoverySuggestion]] delegate:nil cancelButtonTitle:NSLocalizedString(@"Ok", nil) otherButtonTitles:nil]; - [alert show]; - - NSLog(@"A problem occured %@", [error description]); - }; - - // Enumerate Albums - [self.library enumerateGroupsWithTypes:ALAssetsGroupAll - usingBlock:assetGroupEnumerator - failureBlock:assetGroupEnumberatorFailure]; - - } + @autoreleasepool { + + // Group enumerator Block + void (^assetGroupEnumerator)(ALAssetsGroup *, BOOL *) = ^(ALAssetsGroup *group, BOOL *stop) + { + if (group == nil) { + [self performSelectorOnMainThread:@selector(reloadTableView) withObject:nil waitUntilDone:YES]; + 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]; + } + }; + + // Group Enumerator Failure Block + void (^assetGroupEnumberatorFailure)(NSError *) = ^(NSError *error) { + + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Error", nil) message:[NSString stringWithFormat:@"Album Error: %@ - %@", [error localizedDescription], [error localizedRecoverySuggestion]] delegate:nil cancelButtonTitle:NSLocalizedString(@"Ok", nil) otherButtonTitles:nil]; + [alert show]; + + NSLog(@"A problem occurred %@", [error description]); + }; + + // Enumerate Albums + [self.library enumerateGroupsWithTypes:ALAssetsGroupAll + usingBlock:assetGroupEnumerator + failureBlock:assetGroupEnumberatorFailure]; + + } }); + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(checkAlbums) name:ALAssetsLibraryChangedNotification object:nil]; } - (void)viewWillAppear:(BOOL)animated { - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reloadTableView) name:ALAssetsLibraryChangedNotification object:nil]; + self.loadedGroupID = @""; [self.tableView reloadData]; } -- (void)viewWillDisappear:(BOOL)animated { +- (void)didReceiveMemoryWarning { + + [[NSNotificationCenter defaultCenter] removeObserver:self name:ALAssetsLibraryChangedNotification object:nil]; +} + +- (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self name:ALAssetsLibraryChangedNotification object:nil]; } -- (void)reloadTableView +- (void)checkAlbums { - [self.tableView reloadData]; - [self.navigationItem setTitle:NSLocalizedString(@"Select an Album", nil)]; + if (!self.tempAssetGroups) { + self.tempAssetGroups = [[NSMutableArray alloc] initWithCapacity:0]; + } + [self.tempAssetGroups removeAllObjects]; + + // Load Albums into assetGroups + dispatch_async(dispatch_get_main_queue(), ^ + { + @autoreleasepool { + + // Group enumerator Block + void (^assetGroupEnumeratorCheck)(ALAssetsGroup *, BOOL *) = ^(ALAssetsGroup *group, BOOL *stop) + { + if (group == nil) { // End of the enumeration + + NSMutableArray *arrayTemp = [[NSMutableArray alloc] initWithCapacity:1]; + + // Check if an album has been added + for (ALAssetsGroup *group1 in self.tempAssetGroups) { + BOOL albumExists = NO; + NSString *groupID1 = (NSString *)[group1 valueForProperty:ALAssetsGroupPropertyPersistentID]; + + for (ALAssetsGroup *group2 in self.assetGroups) { + NSString *groupID2 = (NSString *)[group2 valueForProperty:ALAssetsGroupPropertyPersistentID]; + + if ([groupID1 isEqualToString:groupID2]) { + albumExists = YES; + break; + } + } + if (!albumExists) { + [arrayTemp addObject: group1]; + } + } + //Add the new albums + if (arrayTemp.count > 0) { + [self.assetGroups addObjectsFromArray:arrayTemp]; + } + [arrayTemp removeAllObjects]; + + // Check if an album has been deleted + for (ALAssetsGroup *group1 in self.assetGroups) { + BOOL albumExists = NO; + NSString *groupID1 = (NSString *)[group1 valueForProperty:ALAssetsGroupPropertyPersistentID]; + + for (ALAssetsGroup *group2 in self.tempAssetGroups) { + NSString *groupID2 = (NSString *)[group2 valueForProperty:ALAssetsGroupPropertyPersistentID]; + + if ([groupID1 isEqualToString:groupID2]) { + albumExists = YES; + break; + } + } + if (!albumExists) { + [arrayTemp addObject:group1]; + } + } + + //Remove the deleted albums + if (arrayTemp.count > 0) { + [self.assetGroups removeObjectsInArray:arrayTemp]; + } + + // If an album is loaded, check if it has been deleted to get back + if (self.loadedGroupID.length > 0) { + BOOL albumExists = NO; + for (ALAssetsGroup *group in self.tempAssetGroups) { + NSString *groupID = (NSString *)[group valueForProperty:ALAssetsGroupPropertyPersistentID]; + if ([groupID isEqualToString:self.loadedGroupID]) { + albumExists = YES; + break; + } + } + + // If the loaded album has been deleted pop the picker viewcontroller + if (!albumExists) { + [self.picker returnBack]; + } + }else { + [self performSelectorOnMainThread:@selector(reloadTableView) withObject:nil waitUntilDone:YES]; + } + + 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.tempAssetGroups insertObject:group atIndex:0]; + } + else { + [self.tempAssetGroups addObject:group]; + } + }; + + // Group Enumerator Failure Block + void (^assetGroupEnumberatorFailure)(NSError *) = ^(NSError *error) { + + UIAlertView * alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Error", nil) message:[NSString stringWithFormat:@"Album Error: %@ - %@", [error localizedDescription], [error localizedRecoverySuggestion]] delegate:nil cancelButtonTitle:NSLocalizedString(@"Ok", nil) otherButtonTitles:nil]; + [alert show]; + + NSLog(@"A problem occured %@", [error description]); + }; + + if (!self.library) { + self.library = [[ALAssetsLibrary alloc] init]; + } + + // Enumerate Albums + [self.library enumerateGroupsWithTypes:ALAssetsGroupAll + usingBlock:assetGroupEnumeratorCheck + failureBlock:assetGroupEnumberatorFailure]; + + } + }); +} + +- (void)reloadTableView { + + [self.tableView reloadData]; + [self.navigationItem setTitle:NSLocalizedString(@"Select an Album", nil)]; } - (BOOL)shouldSelectAsset:(ELCAsset *)asset previousCount:(NSUInteger)previousCount @@ -111,6 +238,15 @@ - (BOOL)shouldDeselectAsset:(ELCAsset *)asset previousCount:(NSUInteger)previous return [self.parent shouldDeselectAsset:asset previousCount:previousCount]; } +- (BOOL)isSelectableIndexNumber:(NSUInteger)indexNumber { + + if ([self.parent respondsToSelector:@selector(isSelectableIndexNumber:)]) { + return [self.parent isSelectableIndexNumber:indexNumber]; + }else { + return NO; + } +} + - (void)selectedAssets:(NSArray*)assets { [_parent selectedAssets:assets]; @@ -176,15 +312,16 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - ELCAssetTablePicker *picker = [[ELCAssetTablePicker alloc] initWithNibName: nil bundle: nil]; - picker.parent = self; - - picker.assetGroup = [self.assetGroups objectAtIndex:indexPath.row]; - [picker.assetGroup setAssetsFilter:[self assetFilter]]; - - picker.assetPickerFilterDelegate = self.assetPickerFilterDelegate; + self.picker = [[ELCAssetTablePicker alloc] initWithNibName: nil bundle: nil]; + self.picker.parent = self; + self.picker.assetGroup = [self.assetGroups objectAtIndex:indexPath.row]; + [self.picker.assetGroup setAssetsFilter:[self assetFilter]]; + self.picker.assetPickerFilterDelegate = self.assetPickerFilterDelegate; - [self.navigationController pushViewController:picker animated:YES]; + // Store the persistentID of the album to load + self.loadedGroupID = (NSString *)[self.picker.assetGroup valueForProperty:ALAssetsGroupPropertyPersistentID]; + + [self.navigationController pushViewController:self.picker animated:YES]; } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath diff --git a/Classes/ELCImagePicker/ELCAsset.h b/Classes/ELCImagePicker/ELCAsset.h index b812d77..3775640 100755 --- a/Classes/ELCImagePicker/ELCAsset.h +++ b/Classes/ELCImagePicker/ELCAsset.h @@ -15,6 +15,7 @@ @optional - (void)assetSelected:(ELCAsset *)asset; - (BOOL)shouldSelectAsset:(ELCAsset *)asset; +- (BOOL)isSelectable; - (void)assetDeselected:(ELCAsset *)asset; - (BOOL)shouldDeselectAsset:(ELCAsset *)asset; @end @@ -25,6 +26,7 @@ @property (nonatomic, strong) ALAsset *asset; @property (nonatomic, weak) id parent; @property (nonatomic, assign) BOOL selected; +@property (nonatomic, readonly, getter = isSelectable) BOOL selectable; @property (nonatomic,assign) int index; - (id)initWithAsset:(ALAsset *)asset; diff --git a/Classes/ELCImagePicker/ELCAsset.m b/Classes/ELCImagePicker/ELCAsset.m index a664192..e54b74e 100755 --- a/Classes/ELCImagePicker/ELCAsset.m +++ b/Classes/ELCImagePicker/ELCAsset.m @@ -58,6 +58,15 @@ - (void)setSelected:(BOOL)selected } } +- (BOOL)isSelectable { + + if ([_parent respondsToSelector:@selector(isSelectable)]) { + return [_parent isSelectable]; + }else { + return NO; + } +} + - (NSComparisonResult)compareWithIndex:(ELCAsset *)_ass { if (self.index > _ass.index) { diff --git a/Classes/ELCImagePicker/ELCAssetCell.m b/Classes/ELCImagePicker/ELCAssetCell.m index d456b11..7fd57b2 100755 --- a/Classes/ELCImagePicker/ELCAssetCell.m +++ b/Classes/ELCImagePicker/ELCAssetCell.m @@ -94,21 +94,30 @@ - (void)cellTapped:(UITapGestureRecognizer *)tapRecognizer CGRect frame = CGRectMake(startX, 2, 75, 75); - for (int i = 0; i < [_rowAssets count]; ++i) { + for (int i = 0; i < [_rowAssets count]; ++i) { if (CGRectContainsPoint(frame, point)) { ELCAsset *asset = [_rowAssets objectAtIndex:i]; - asset.selected = !asset.selected; ELCOverlayImageView *overlayView = [_overlayViewArray objectAtIndex:i]; - overlayView.hidden = !asset.selected; - if (asset.selected) { + + // If the asset is not selected check if it could be selected + if (!asset.selected && [asset isSelectable]) { + asset.selected = !asset.selected; + overlayView.hidden = !asset.selected; + asset.index = [[ELCConsole mainConsole] numOfSelectedElements]; [overlayView setIndex:asset.index+1]; [[ELCConsole mainConsole] addIndex:asset.index]; - } - else - { + }else if(asset.selected) { // If the asset is going to be unselected + asset.selected = !asset.selected; + overlayView.hidden = !asset.selected; + + asset.index = 0; + [overlayView setIndex:asset.index]; int lastElement = [[ELCConsole mainConsole] numOfSelectedElements] - 1; [[ELCConsole mainConsole] removeIndex:lastElement]; + }else if (!asset.selected && ![asset isSelectable]) { + // If the asset isn't selected and is not selectable, try to select to show a message to the user + asset.selected = !asset.selected; } break; } diff --git a/Classes/ELCImagePicker/ELCAssetSelectionDelegate.h b/Classes/ELCImagePicker/ELCAssetSelectionDelegate.h index b8dba83..c08cf0d 100755 --- a/Classes/ELCImagePicker/ELCAssetSelectionDelegate.h +++ b/Classes/ELCImagePicker/ELCAssetSelectionDelegate.h @@ -15,5 +15,6 @@ - (void)selectedAssets:(NSArray *)assets; - (BOOL)shouldSelectAsset:(ELCAsset *)asset previousCount:(NSUInteger)previousCount; - (BOOL)shouldDeselectAsset:(ELCAsset *)asset previousCount:(NSUInteger)previousCount; +- (BOOL)isSelectableIndexNumber:(NSUInteger)indexNumber; @end diff --git a/Classes/ELCImagePicker/ELCAssetTablePicker.h b/Classes/ELCImagePicker/ELCAssetTablePicker.h index 8148ef6..b7ce5d0 100755 --- a/Classes/ELCImagePicker/ELCAssetTablePicker.h +++ b/Classes/ELCImagePicker/ELCAssetTablePicker.h @@ -23,8 +23,8 @@ // optional, can be used to filter the assets displayed @property(nonatomic, weak) id assetPickerFilterDelegate; +- (void)returnBack; - (int)totalSelectedAssets; -- (void)preparePhotos; - (void)doneAction:(id)sender; diff --git a/Classes/ELCImagePicker/ELCAssetTablePicker.m b/Classes/ELCImagePicker/ELCAssetTablePicker.m index 24830be..a41b75c 100755 --- a/Classes/ELCImagePicker/ELCAssetTablePicker.m +++ b/Classes/ELCImagePicker/ELCAssetTablePicker.m @@ -51,7 +51,7 @@ - (void)viewDidLoad [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]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(refreshAssets) name:ALAssetsLibraryChangedNotification object:nil]; } - (void)viewWillAppear:(BOOL)animated @@ -64,6 +64,15 @@ - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; [[ELCConsole mainConsole] removeAllIndex]; +} + +- (void)didReceiveMemoryWarning { + + [[NSNotificationCenter defaultCenter] removeObserver:self name:ALAssetsLibraryChangedNotification object:nil]; +} + +- (void)dealloc { + [[NSNotificationCenter defaultCenter] removeObserver:self name:ALAssetsLibraryChangedNotification object:nil]; } @@ -84,6 +93,7 @@ - (void)preparePhotos @autoreleasepool { [self.elcAssets removeAllObjects]; + [[ELCConsole mainConsole] removeAllIndex]; [self.assetGroup enumerateAssetsUsingBlock:^(ALAsset *result, NSUInteger index, BOOL *stop) { if (result == nil) { @@ -104,7 +114,7 @@ - (void)preparePhotos [self.elcAssets addObject:elcAsset]; } - }]; + }]; dispatch_sync(dispatch_get_main_queue(), ^{ [self.tableView reloadData]; @@ -124,6 +134,15 @@ - (void)preparePhotos } } +- (void)refreshAssets { + + [self performSelectorInBackground:@selector(preparePhotos) withObject:nil]; +} + +- (void)returnBack { + + [self.navigationController popViewControllerAnimated:YES]; +} - (void)doneAction:(id)sender { @@ -154,6 +173,20 @@ - (BOOL)shouldSelectAsset:(ELCAsset *)asset return shouldSelect; } +- (BOOL)isSelectable { + + NSUInteger selectionCount = 0; + for (ELCAsset *elcAsset in self.elcAssets) { + if (elcAsset.selected) selectionCount++; + } + + if ([self.parent respondsToSelector:@selector(isSelectableIndexNumber:)]) { + return [self.parent isSelectableIndexNumber:selectionCount]; + }else { + return NO; + } +} + - (void)assetSelected:(ELCAsset *)asset { if (self.singleSelection) { diff --git a/Classes/ELCImagePicker/ELCImagePickerController.m b/Classes/ELCImagePicker/ELCImagePickerController.m index b7f3eda..2ddd7fc 100755 --- a/Classes/ELCImagePicker/ELCImagePickerController.m +++ b/Classes/ELCImagePicker/ELCImagePickerController.m @@ -87,6 +87,11 @@ - (BOOL)shouldDeselectAsset:(ELCAsset *)asset previousCount:(NSUInteger)previous return YES; } +- (BOOL)isSelectableIndexNumber:(NSUInteger)indexNumber { + + return (indexNumber < self.maximumImagesCount); +} + - (void)selectedAssets:(NSArray *)assets { NSMutableArray *returnArray = [[NSMutableArray alloc] init]; diff --git a/Classes/ELCImagePickerDemoViewController.m b/Classes/ELCImagePickerDemoViewController.m index 0b53ef2..92f5706 100644 --- a/Classes/ELCImagePickerDemoViewController.m +++ b/Classes/ELCImagePickerDemoViewController.m @@ -25,8 +25,8 @@ - (IBAction)launchController { ELCImagePickerController *elcPicker = [[ELCImagePickerController alloc] initImagePicker]; - elcPicker.maximumImagesCount = 100; //Set the maximum number of images to select to 100 - elcPicker.returnsOriginalImage = YES; //Only return the fullScreenImage, not the fullResolutionImage + elcPicker.maximumImagesCount = 8; //Set the maximum number of images to select to 100 + elcPicker.returnsOriginalImage = NO; //Only return the fullScreenImage, not the fullResolutionImage elcPicker.returnsImage = YES; //Return UIimage if YES. If NO, only return asset location information elcPicker.onOrder = YES; //For multiple image selection, display and return order of selected images elcPicker.mediaTypes = @[(NSString *)kUTTypeImage, (NSString *)kUTTypeMovie]; //Supports image and movie types