From 801c6b6f288ee80486c61a2cf205bb5644ad6be9 Mon Sep 17 00:00:00 2001 From: Stephenie Harris Date: Tue, 31 Jul 2018 12:23:14 -0600 Subject: [PATCH 1/6] Adding support to use a View Controller for the empty view. --- Pod/Classes/WPMediaPickerViewController.h | 22 +++- Pod/Classes/WPMediaPickerViewController.m | 110 ++++++++++++++++-- .../WPNavigationMediaPickerViewController.m | 7 ++ 3 files changed, 131 insertions(+), 8 deletions(-) diff --git a/Pod/Classes/WPMediaPickerViewController.h b/Pod/Classes/WPMediaPickerViewController.h index 89863df9..60a1b856 100644 --- a/Pod/Classes/WPMediaPickerViewController.h +++ b/Pod/Classes/WPMediaPickerViewController.h @@ -198,6 +198,19 @@ */ - (nullable UIView *)emptyViewForMediaPickerController:(nonnull WPMediaPickerViewController *)picker; +/** + * Asks the delegate for an empty view to show when there are no assets + * to be displayed. If no empty view is required, you have to implement this + * method and return `nil`. + * + * @param picker The controller object managing the assets picker interface. + * @return An empty view controller to display or `nil` to not display any. + * + * If this method is not implemented, a default ViewController with a default + * UILabel will be displayed. + */ +- (nullable UIViewController *)emptyViewControllerForMediaPickerController:(nonnull WPMediaPickerViewController *)picker; + @end @@ -234,10 +247,17 @@ @property (nonatomic, strong, readonly, nullable) UISearchBar *searchBar; /** - The default empty view. When `emptyViewForMediaPickerController:` is not implemented, use this property to style the mensaje. + The default empty view. When `emptyViewForMediaPickerController:` is not implemented, + use this property to style the message. */ @property (nonatomic, strong, readonly, nonnull) UILabel *defaultEmptyView; +/** + The default empty view controller. When `emptyViewControllerForMediaPickerController:` is not implemented, + use this property to style the message. + */ +@property (nonatomic, strong, readonly, nonnull) UIViewController *defaultEmptyViewController; + /** A localized string that reflect the action that will be done when the user finishes picking assets. This string can contain a a placeholder for a numeric value that will indicate the number of media items selected. diff --git a/Pod/Classes/WPMediaPickerViewController.m b/Pod/Classes/WPMediaPickerViewController.m index cd440207..23089c0d 100644 --- a/Pod/Classes/WPMediaPickerViewController.m +++ b/Pod/Classes/WPMediaPickerViewController.m @@ -49,6 +49,9 @@ @interface WPMediaPickerViewController () @property (nonatomic, strong) UIView *emptyView; @property (nonatomic, strong) UILabel *defaultEmptyView; +@property (nonatomic, strong) UIViewController *emptyViewController; +@property (nonatomic, strong) UIViewController *defaultEmptyViewController; + @property (nonatomic, strong) WPActionBar *accessoryActionBar; @property (nonatomic, strong) UIButton *selectedActionButton; @@ -553,6 +556,8 @@ - (void)showCapture { return; } +#pragma mark - Empty View support + - (UIView *)emptyView { if (_emptyView) { @@ -570,8 +575,12 @@ - (UIView *)emptyView - (void)addEmptyViewToView { - if (self.emptyView.superview == nil) { - [self.collectionView addSubview:_emptyView]; + if ([self usingEmptyViewController]) { + [self addEmptyViewControllerToView]; + } else { + if (self.emptyView.superview == nil) { + [self.collectionView addSubview:_emptyView]; + } } } @@ -586,6 +595,63 @@ - (UILabel *)defaultEmptyView return _defaultEmptyView; } +#pragma mark - Empty View Controller support + +- (void)addEmptyViewControllerToView +{ + if (self.emptyViewController.view.superview == nil) { + [self.collectionView addSubview:self.emptyViewController.view]; + _emptyViewController.view.frame = self.collectionView.frame; + [self addChildViewController:_emptyViewController]; + [_emptyViewController didMoveToParentViewController:self]; + } +} + +- (void)removeEmptyViewControllerFromView +{ + [_emptyViewController willMoveToParentViewController:nil]; + [_emptyViewController.view removeFromSuperview]; + [_emptyViewController removeFromParentViewController]; +} + +- (UIViewController *)emptyViewController +{ + if (_emptyViewController) { + return _emptyViewController; + } + + if ([self usingEmptyViewController]) { + _emptyViewController = [self.mediaPickerDelegate emptyViewControllerForMediaPickerController:self]; + } + else { + _emptyViewController = self.defaultEmptyViewController; + } + + return _emptyViewController; +} + +- (UIViewController *)defaultEmptyViewController +{ + if (_defaultEmptyViewController) { + return _defaultEmptyViewController; + } + + _defaultEmptyViewController = [[UIViewController alloc] init]; + + UILabel *emptyViewLabel = [[UILabel alloc] init]; + emptyViewLabel.text = NSLocalizedString(@"Nothing to show", @"Default message for empty media picker"); + [emptyViewLabel sizeToFit]; + emptyViewLabel.center = _defaultEmptyViewController.view.center; + [[_defaultEmptyViewController view] addSubview:emptyViewLabel]; + + return _defaultEmptyViewController; +} + +- (BOOL)usingEmptyViewController +{ + return [self.mediaPickerDelegate respondsToSelector:@selector(emptyViewControllerForMediaPickerController:)]; +} + #pragma mark - UICollectionViewDataSource - (void)updateDataWithRemoved:(NSIndexSet *)removed inserted:(NSIndexSet *)inserted changed:(NSIndexSet *)changed moved:(NSArray> *)moves { @@ -782,11 +848,25 @@ - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSe [self.mediaPickerDelegate mediaPickerController:self didUpdateSearchWithAssetCount:numberOfAssets]; } - [self.emptyView setHidden:(numberOfAssets != 0)]; + [self toggleEmptyViewFor:numberOfAssets]; return numberOfAssets; } +- (void)toggleEmptyViewFor:(NSInteger)numberOfAssets +{ + if ([self usingEmptyViewController]) { + if (numberOfAssets > 0) { + [self removeEmptyViewControllerFromView]; + } else { + [self addEmptyViewControllerToView]; + } + } else { + [self.emptyView setHidden:(numberOfAssets != 0)]; + } +} + + - (id)assetForPosition:(NSIndexPath *)indexPath { NSInteger itemPosition = indexPath.item; @@ -1342,22 +1422,38 @@ - (void)keyboardWillHideNotification:(NSNotification *)notification [self.collectionView.collectionViewLayout invalidateLayout]; } - /** Centers the empty view taking into account the collection view height and content insets. */ - (void)centerEmptyView { - self.emptyView.center = self.collectionView.center; + if (self.emptyViewController) { + CGRect emptyViewFrame = [self getEmptyViewFrame]; + emptyViewFrame.origin.y -= self.searchBar.frame.size.height/2; + self.emptyViewController.view.frame = emptyViewFrame; + } else { + self.emptyView.center = self.collectionView.center; + self.emptyView.frame = [self getEmptyViewFrame]; + } +} + +- (CGRect)getEmptyViewFrame +{ + CGRect emptyViewFrame; + + if (_emptyViewController) { + emptyViewFrame = self.collectionView.frame; + } else { + emptyViewFrame = self.emptyView.frame; + } - CGRect emptyViewFrame = self.emptyView.frame; CGFloat superviewHeight = self.collectionView.frame.size.height; CGFloat totalInsets = self.collectionView.contentInset.top + self.collectionView.contentInset.bottom; superviewHeight = superviewHeight - totalInsets > 0 ? superviewHeight - totalInsets : superviewHeight; emptyViewFrame.origin.y = (superviewHeight / 2.0) - (emptyViewFrame.size.height / 2.0) + self.collectionView.frame.origin.y; - self.emptyView.frame = emptyViewFrame; + return emptyViewFrame; } #pragma mark - UIViewControllerPreviewingDelegate diff --git a/Pod/Classes/WPNavigationMediaPickerViewController.m b/Pod/Classes/WPNavigationMediaPickerViewController.m index 54537f99..2ba1a8c5 100644 --- a/Pod/Classes/WPNavigationMediaPickerViewController.m +++ b/Pod/Classes/WPNavigationMediaPickerViewController.m @@ -200,6 +200,13 @@ - (UIView *)emptyViewForMediaPickerController:(WPMediaPickerViewController *)pic return picker.defaultEmptyView; } +- (UIViewController *)emptyViewControllerForMediaPickerController:(WPMediaPickerViewController *)picker { + if ([self.delegate respondsToSelector:@selector(emptyViewControllerForMediaPickerController:)]) { + return [self.delegate emptyViewControllerForMediaPickerController:picker]; + } + return picker.defaultEmptyViewController; +} + - (void)mediaPickerController:(nonnull WPMediaPickerViewController *)picker didFinishPickingAssets:(nonnull NSArray *)assets { if ([self.delegate respondsToSelector:@selector(mediaPickerController:didFinishPickingAssets:)]) { [self.delegate mediaPickerController:picker didFinishPickingAssets:assets]; From 73c441f6973dcf1bf2e0ce59b0212635b14d72a3 Mon Sep 17 00:00:00 2001 From: Stephenie Harris Date: Wed, 1 Aug 2018 12:59:12 -0600 Subject: [PATCH 2/6] Remove `defaultEmptyViewController` as a public property. Have `defaultEmptyViewController` use `defaultEmptyView` instead of creating its own. Add `defaultEmptyViewController` accessor since `WPNavigationMediaPickerViewController` needs it. --- Pod/Classes/WPMediaPickerViewController.h | 13 +++++++------ Pod/Classes/WPMediaPickerViewController.m | 7 ++----- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/Pod/Classes/WPMediaPickerViewController.h b/Pod/Classes/WPMediaPickerViewController.h index 60a1b856..2af37572 100644 --- a/Pod/Classes/WPMediaPickerViewController.h +++ b/Pod/Classes/WPMediaPickerViewController.h @@ -252,12 +252,6 @@ */ @property (nonatomic, strong, readonly, nonnull) UILabel *defaultEmptyView; -/** - The default empty view controller. When `emptyViewControllerForMediaPickerController:` is not implemented, - use this property to style the message. - */ -@property (nonatomic, strong, readonly, nonnull) UIViewController *defaultEmptyViewController; - /** A localized string that reflect the action that will be done when the user finishes picking assets. This string can contain a a placeholder for a numeric value that will indicate the number of media items selected. @@ -313,6 +307,13 @@ */ - (nonnull UIViewController *)defaultPreviewViewControllerForAsset:(nonnull id)asset; +/** + Return a View Controller to present `defaultEmptyView`. + + @return a view controller to present the empty view. + */ +- (UIViewController *)defaultEmptyViewController; + /** Calculates the appropriate cell height/width given the desired number of cells per line, desired space between cells, and total width of the frame containing the cells. diff --git a/Pod/Classes/WPMediaPickerViewController.m b/Pod/Classes/WPMediaPickerViewController.m index 23089c0d..36b5d011 100644 --- a/Pod/Classes/WPMediaPickerViewController.m +++ b/Pod/Classes/WPMediaPickerViewController.m @@ -637,10 +637,7 @@ - (UIViewController *)defaultEmptyViewController } _defaultEmptyViewController = [[UIViewController alloc] init]; - - UILabel *emptyViewLabel = [[UILabel alloc] init]; - emptyViewLabel.text = NSLocalizedString(@"Nothing to show", @"Default message for empty media picker"); - [emptyViewLabel sizeToFit]; + UILabel *emptyViewLabel = self.defaultEmptyView; emptyViewLabel.center = _defaultEmptyViewController.view.center; [[_defaultEmptyViewController view] addSubview:emptyViewLabel]; @@ -1430,7 +1427,7 @@ - (void)centerEmptyView if (self.emptyViewController) { CGRect emptyViewFrame = [self getEmptyViewFrame]; emptyViewFrame.origin.y -= self.searchBar.frame.size.height/2; - self.emptyViewController.view.frame = emptyViewFrame; + _emptyViewController.view.frame = emptyViewFrame; } else { self.emptyView.center = self.collectionView.center; self.emptyView.frame = [self getEmptyViewFrame]; From c50cf0bc0425df4c41827a8b6739b805b91c0029 Mon Sep 17 00:00:00 2001 From: Stephenie Harris Date: Wed, 1 Aug 2018 13:23:45 -0600 Subject: [PATCH 3/6] Center empty view when `emptyViewController` added to view. To resolve issue where it was appearing under the keyboard when it refreshed. --- Pod/Classes/WPMediaPickerViewController.m | 1 + 1 file changed, 1 insertion(+) diff --git a/Pod/Classes/WPMediaPickerViewController.m b/Pod/Classes/WPMediaPickerViewController.m index 36b5d011..aaee7016 100644 --- a/Pod/Classes/WPMediaPickerViewController.m +++ b/Pod/Classes/WPMediaPickerViewController.m @@ -604,6 +604,7 @@ - (void)addEmptyViewControllerToView _emptyViewController.view.frame = self.collectionView.frame; [self addChildViewController:_emptyViewController]; [_emptyViewController didMoveToParentViewController:self]; + [self centerEmptyView]; } } From d9857c2e94a1d5a8fcd09a048b7ad846ef567e8f Mon Sep 17 00:00:00 2001 From: Stephenie Harris Date: Wed, 1 Aug 2018 13:57:06 -0600 Subject: [PATCH 4/6] Adding animation to slightly slow down re-centering the empty view. --- Pod/Classes/WPMediaPickerViewController.m | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/Pod/Classes/WPMediaPickerViewController.m b/Pod/Classes/WPMediaPickerViewController.m index aaee7016..e936e4d4 100644 --- a/Pod/Classes/WPMediaPickerViewController.m +++ b/Pod/Classes/WPMediaPickerViewController.m @@ -1397,9 +1397,10 @@ - (void)keyboardWillShowNotification:(NSNotification *)notification self.collectionView.contentInset = contentInset; self.collectionView.scrollIndicatorInsets = contentInset; - [self centerEmptyView]; - - [self.collectionView.collectionViewLayout invalidateLayout]; + [UIView animateWithDuration:0.2 animations:^{ + [self centerEmptyView]; + [self.collectionView.collectionViewLayout invalidateLayout]; + }]; } - (void)keyboardWillHideNotification:(NSNotification *)notification @@ -1415,9 +1416,10 @@ - (void)keyboardWillHideNotification:(NSNotification *)notification self.collectionView.contentInset = contentInset; self.collectionView.scrollIndicatorInsets = contentInset; - [self centerEmptyView]; - - [self.collectionView.collectionViewLayout invalidateLayout]; + [UIView animateWithDuration:0.2 animations:^{ + [self centerEmptyView]; + [self.collectionView.collectionViewLayout invalidateLayout]; + }]; } /** From bceb4f096db7ff03d2e1cd2e0ccf55855b186afe Mon Sep 17 00:00:00 2001 From: Stephenie Harris Date: Thu, 2 Aug 2018 14:29:28 -0600 Subject: [PATCH 5/6] Don't show the refreshControl if emptyViewController is being displayed. --- Pod/Classes/WPMediaPickerViewController.m | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Pod/Classes/WPMediaPickerViewController.m b/Pod/Classes/WPMediaPickerViewController.m index e936e4d4..3b5b079c 100644 --- a/Pod/Classes/WPMediaPickerViewController.m +++ b/Pod/Classes/WPMediaPickerViewController.m @@ -697,7 +697,11 @@ - (void)refreshData - (void)refreshDataAnimated:(BOOL)animated { - [self.refreshControl beginRefreshing]; + // Don't show the refreshControl if emptyViewController is being displayed. + if (! _emptyViewController) { + [self.refreshControl beginRefreshing]; + } + self.collectionView.allowsSelection = NO; self.collectionView.allowsMultipleSelection = NO; self.collectionView.scrollEnabled = NO; From 685607c33f94160aa95998ab5c476e1c6979a16e Mon Sep 17 00:00:00 2001 From: Stephenie Harris Date: Fri, 3 Aug 2018 11:05:37 -0600 Subject: [PATCH 6/6] Updating pod version to 1.2. --- WPMediaPicker.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WPMediaPicker.podspec b/WPMediaPicker.podspec index 4c21e239..3be11036 100644 --- a/WPMediaPicker.podspec +++ b/WPMediaPicker.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "WPMediaPicker" - s.version = "1.1" + s.version = "1.2" s.summary = "WPMediaPicker is an iOS controller that allows capture and picking of media assets." s.description = <<-DESC WPMediaPicker is an iOS controller that allows capture and picking of media assets.