diff --git a/Pod/Classes/UIViewController+MediaAdditions.m b/Pod/Classes/UIViewController+MediaAdditions.m index 920b0ec..e66a2a8 100644 --- a/Pod/Classes/UIViewController+MediaAdditions.m +++ b/Pod/Classes/UIViewController+MediaAdditions.m @@ -1,40 +1,11 @@ #import "UIViewController+MediaAdditions.h" #import "WPMediaCollectionDataSource.h" +#import "WPMediaPickerAlertHelper.h" @implementation UIViewController (MediaAdditions) - (void)wpm_showAlertWithError:(NSError *)error okActionHandler:(void (^ __nullable)(UIAlertAction *action))handler { - NSString *title = NSLocalizedString(@"Media Library", @"Title for alert when a generic error happened when loading media"); - NSString *message = NSLocalizedString(@"There was a problem when trying to access your media. Please try again later.", @"Explaining to the user there was an generic error accesing media."); - NSString *cancelText = NSLocalizedString(@"OK", ""); - NSString *otherButtonTitle = nil; - if (error.domain == WPMediaPickerErrorDomain) { - title = NSLocalizedString(@"Media Library", @"Title for alert when access to the media library is not granted by the user"); - if (error.code == WPMediaPickerErrorCodePermissionDenied) { - otherButtonTitle = NSLocalizedString(@"Open Settings", @"Go to the settings app"); - message = NSLocalizedString(@"This app needs permission to access your device media library in order to add photos and/or video to your posts. Please change the privacy settings if you wish to allow this.", - @"Explaining to the user why the app needs access to the device media library."); - } else if (error.code == WPMediaPickerErrorCodeRestricted) { - message = NSLocalizedString(@"Your app is not authorized to access media library due to active restrictions such as parental controls. Please check your parental control settings in this device.", - @"Explaining to the user why the app needs access to the device media library."); - } - } - - UIAlertController *alertController = [UIAlertController alertControllerWithTitle:title - message:message - preferredStyle:UIAlertControllerStyleAlert]; - UIAlertAction *okAction = [UIAlertAction actionWithTitle:cancelText - style:UIAlertActionStyleCancel - handler:handler]; - [alertController addAction:okAction]; - - if (otherButtonTitle) { - UIAlertAction *otherAction = [UIAlertAction actionWithTitle:otherButtonTitle style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { - NSURL *settingsURL = [NSURL URLWithString:UIApplicationOpenSettingsURLString]; - [[UIApplication sharedApplication] openURL:settingsURL options:@{} completionHandler:nil]; - }]; - [alertController addAction:otherAction]; - } + UIAlertController *alertController = [WPMediaPickerAlertHelper buildAlertControllerWithError:error okActionHandler:handler]; [self presentViewController:alertController animated:YES completion:nil]; } diff --git a/Pod/Classes/WPMediaPicker.h b/Pod/Classes/WPMediaPicker.h index 5c9c46a..dc7f7f1 100644 --- a/Pod/Classes/WPMediaPicker.h +++ b/Pod/Classes/WPMediaPicker.h @@ -15,5 +15,6 @@ #import "WPMediaCapturePreviewCollectionView.h" #import "WPVideoPlayerView.h" #import "WPActionBar.h" +#import "WPMediaPickerAlertHelper.h" #endif /* _WPMEDIAPICKER_ */ diff --git a/Pod/Classes/WPMediaPickerAlertHelper.h b/Pod/Classes/WPMediaPickerAlertHelper.h new file mode 100644 index 0000000..3f83df2 --- /dev/null +++ b/Pod/Classes/WPMediaPickerAlertHelper.h @@ -0,0 +1,8 @@ +#import + +@interface WPMediaPickerAlertHelper : NSObject + ++ (nonnull UIAlertController *)buildAlertControllerWithError:(NSError * _Nullable)error + okActionHandler:(void (^ __nullable)(UIAlertAction * _Nullable action))handler; + +@end diff --git a/Pod/Classes/WPMediaPickerAlertHelper.m b/Pod/Classes/WPMediaPickerAlertHelper.m new file mode 100644 index 0000000..6657e10 --- /dev/null +++ b/Pod/Classes/WPMediaPickerAlertHelper.m @@ -0,0 +1,43 @@ +#import "WPMediaPickerAlertHelper.h" +#import "WPMediaCollectionDataSource.h" + +@implementation WPMediaPickerAlertHelper + ++ (nonnull UIAlertController *)buildAlertControllerWithError:(NSError * _Nullable)error + okActionHandler:(void (^ __nullable)(UIAlertAction * _Nullable action))handler { + NSString *title = NSLocalizedString(@"Media Library", @"Title for alert when a generic error happened when loading media"); + NSString *message = NSLocalizedString(@"There was a problem when trying to access your media. Please try again later.", @"Explaining to the user there was an generic error accesing media."); + NSString *cancelText = NSLocalizedString(@"OK", ""); + NSString *otherButtonTitle = nil; + if (error.domain == WPMediaPickerErrorDomain) { + title = NSLocalizedString(@"Media Library", @"Title for alert when access to the media library is not granted by the user"); + if (error.code == WPMediaPickerErrorCodePermissionDenied) { + otherButtonTitle = NSLocalizedString(@"Open Settings", @"Go to the settings app"); + message = NSLocalizedString(@"This app needs permission to access your device media library in order to add photos and/or video to your posts. Please change the privacy settings if you wish to allow this.", + @"Explaining to the user why the app needs access to the device media library."); + } else if (error.code == WPMediaPickerErrorCodeRestricted) { + message = NSLocalizedString(@"Your app is not authorized to access media library due to active restrictions such as parental controls. Please check your parental control settings in this device.", + @"Explaining to the user why the app needs access to the device media library."); + } + } + + UIAlertController *alertController = [UIAlertController alertControllerWithTitle:title + message:message + preferredStyle:UIAlertControllerStyleAlert]; + UIAlertAction *okAction = [UIAlertAction actionWithTitle:cancelText + style:UIAlertActionStyleCancel + handler:handler]; + [alertController addAction:okAction]; + + if (otherButtonTitle) { + UIAlertAction *otherAction = [UIAlertAction actionWithTitle:otherButtonTitle style:UIAlertActionStyleDefault handler:^(UIAlertAction *action) { + NSURL *settingsURL = [NSURL URLWithString:UIApplicationOpenSettingsURLString]; + [[UIApplication sharedApplication] openURL:settingsURL options:@{} completionHandler:nil]; + }]; + [alertController addAction:otherAction]; + } + + return alertController; +} + +@end diff --git a/Pod/Classes/WPMediaPickerViewController.m b/Pod/Classes/WPMediaPickerViewController.m index b70a803..723ff2b 100644 --- a/Pod/Classes/WPMediaPickerViewController.m +++ b/Pod/Classes/WPMediaPickerViewController.m @@ -1193,6 +1193,7 @@ - (void)processMediaCaptured:(NSDictionary *)info WPMediaAddedBlock completionBlock = ^(id media, NSError *error) { if (error || !media) { NSLog(@"Adding media failed: %@", [error localizedDescription]); + [self showError:error]; return; } [self addMedia:media animated:YES]; diff --git a/Pod/Classes/WPPHAssetDataSource.m b/Pod/Classes/WPPHAssetDataSource.m index 48e21d3..d4ba5db 100644 --- a/Pod/Classes/WPPHAssetDataSource.m +++ b/Pod/Classes/WPPHAssetDataSource.m @@ -131,11 +131,7 @@ - (void)loadDataWithOptions:(WPMediaLoadOptions)options { [self checkPermissionStatus:^(PHAuthorizationStatus status) { - /// Starting from iOS 15.2 we should do the registration - /// after asking user for permission - /// Solution proposed here - https://developer.apple.com/forums/thread/696804 - /// - [[PHPhotoLibrary sharedPhotoLibrary] registerChangeObserver:self]; + [self registerPHChangeObserver]; switch (status) { case PHAuthorizationStatusRestricted: @@ -450,40 +446,82 @@ - (void)addAssetWithChangeRequest:(PHAssetChangeRequest *(^)(void))changeRequest { NSParameterAssert(changeRequestBlock); __block NSString * assetIdentifier = nil; - [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{ - // Request creating an asset from the image. - PHAssetChangeRequest *createAssetRequest = changeRequestBlock(); - PHObjectPlaceholder *assetPlaceholder = [createAssetRequest placeholderForCreatedAsset]; - assetIdentifier = [assetPlaceholder localIdentifier]; - if ([self.activeAssetsCollection canPerformEditOperation:PHCollectionEditOperationAddContent]) { - // Request editing the album. - PHAssetCollectionChangeRequest *albumChangeRequest = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:self.activeAssetsCollection]; - [albumChangeRequest addAssets:@[ assetPlaceholder ]]; - } - } completionHandler:^(BOOL success, NSError *error) { - if (!success) { - if (completionBlock){ - dispatch_async(dispatch_get_main_queue(), ^{ - completionBlock(nil, error); - }); + + [self checkPermissionStatus:^(PHAuthorizationStatus status) { + + [self registerPHChangeObserver]; + + switch (status) { + case PHAuthorizationStatusRestricted: + { + if (completionBlock) { + dispatch_async(dispatch_get_main_queue(), ^{ + NSError *error = [NSError errorWithDomain:WPMediaPickerErrorDomain code:WPMediaPickerErrorCodeRestricted userInfo:nil]; + completionBlock(nil, error); + }); + } + return; } - return; - } - PHFetchOptions *fetchOptions = [[PHFetchOptions alloc] init]; - fetchOptions.predicate = [NSPredicate predicateWithFormat:@"(localIdentifier == %@)", assetIdentifier]; - PHFetchResult * result = [PHAsset fetchAssetsWithOptions:fetchOptions]; - if (result.count < 1){ - if (completionBlock){ - dispatch_async(dispatch_get_main_queue(), ^{ - completionBlock(nil, error); + case PHAuthorizationStatusDenied: + case PHAuthorizationStatusLimited: + { + if (completionBlock) { + dispatch_async(dispatch_get_main_queue(), ^{ + NSError *error = [NSError errorWithDomain:WPMediaPickerErrorDomain code:WPMediaPickerErrorCodePermissionDenied userInfo:nil]; + completionBlock(nil, error); + }); + } + return; + } + case PHAuthorizationStatusNotDetermined: + { + [self checkPermissionStatus:^(PHAuthorizationStatus status) { + [self addAssetWithChangeRequest:changeRequestBlock completionBlock:completionBlock]; + }]; + return; + } + case PHAuthorizationStatusAuthorized: + { + dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), ^{ + [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{ + // Request creating an asset from the image. + PHAssetChangeRequest *createAssetRequest = changeRequestBlock(); + PHObjectPlaceholder *assetPlaceholder = [createAssetRequest placeholderForCreatedAsset]; + assetIdentifier = [assetPlaceholder localIdentifier]; + if ([self.activeAssetsCollection canPerformEditOperation:PHCollectionEditOperationAddContent]) { + // Request editing the album. + PHAssetCollectionChangeRequest *albumChangeRequest = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:self.activeAssetsCollection]; + [albumChangeRequest addAssets:@[ assetPlaceholder ]]; + } + } completionHandler:^(BOOL success, NSError *error) { + if (!success) { + if (completionBlock){ + dispatch_async(dispatch_get_main_queue(), ^{ + completionBlock(nil, error); + }); + } + return; + } + PHFetchOptions *fetchOptions = [[PHFetchOptions alloc] init]; + fetchOptions.predicate = [NSPredicate predicateWithFormat:@"(localIdentifier == %@)", assetIdentifier]; + PHFetchResult * result = [PHAsset fetchAssetsWithOptions:fetchOptions]; + if (result.count < 1){ + if (completionBlock){ + dispatch_async(dispatch_get_main_queue(), ^{ + completionBlock(nil, error); + }); + } + return; + } + if (completionBlock) { + dispatch_async(dispatch_get_main_queue(), ^{ + completionBlock([result firstObject], nil); + }); + } + }]; }); + return; } - return; - } - if (completionBlock) { - dispatch_async(dispatch_get_main_queue(), ^{ - completionBlock([result firstObject], nil); - }); } }]; } @@ -495,6 +533,16 @@ - (void)setMediaTypeFilter:(WPMediaType)filter _refreshGroups = YES; } +- (void)registerPHChangeObserver +{ + + /// Starting from iOS 15.2 we should do the registration + /// after asking user for permission + /// Solution proposed here - https://developer.apple.com/forums/thread/696804 + /// + [[PHPhotoLibrary sharedPhotoLibrary] registerChangeObserver:self]; +} + @end #pragma mark - WPPHAssetMedia diff --git a/WPMediaPicker.podspec b/WPMediaPicker.podspec index 32499b9..f5ea40a 100644 --- a/WPMediaPicker.podspec +++ b/WPMediaPicker.podspec @@ -2,7 +2,7 @@ Pod::Spec.new do |s| s.name = 'WPMediaPicker' - s.version = '1.8.2' + s.version = '1.8.3-beta.1' s.summary = 'WPMediaPicker is an iOS controller that allows capture and picking of media assets.' s.description = <<-DESC