Here is a complete guide for iOS 8+ (without ALAssetLibrary):
Firstly we have to provide the usage description as now it's required by PHPhotoLibrary.
For doing this we must open the file info.plist
, find the key Privacy - Photo Library Usage Description
and provide the value for it. If the key doesn't exist then just create it.
Here is an image for example:
Also make sure that the value of the key Bundle name
is not empty in the info.plist
file.
Now when we have description, we can normally request authorization by calling requestAuthorization
method:
[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
switch (status) {
case PHAuthorizationStatusAuthorized:
NSLog(@"PHAuthorizationStatusAuthorized");
break;
case PHAuthorizationStatusDenied:
NSLog(@"PHAuthorizationStatusDenied");
break;
case PHAuthorizationStatusNotDetermined:
NSLog(@"PHAuthorizationStatusNotDetermined");
break;
case PHAuthorizationStatusRestricted:
NSLog(@"PHAuthorizationStatusRestricted");
break;
}
}];
NOTE 1: requestAuthorization
actually doesn't show alert on every call. It shows once per some time, saves user's answer and returns it everytime instead of showing alert again. But as it isn't what we need, here is a useful code which always shows alert every time we need permission (with redirection to settings):
- (void)requestAuthorizationWithRedirectionToSettings {
dispatch_async(dispatch_get_main_queue(), ^{
PHAuthorizationStatus status = [PHPhotoLibrary authorizationStatus];
if (status == PHAuthorizationStatusAuthorized)
{
//We have permission. Do whatever is needed
}
else
{
//No permission. Trying to normally request it
[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
if (status != PHAuthorizationStatusAuthorized)
{
//User don't give us permission. Showing alert with redirection to settings
//Getting description string from info.plist file
NSString *accessDescription = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"NSPhotoLibraryUsageDescription"];
UIAlertController * alertController = [UIAlertController alertControllerWithTitle:accessDescription message:@"To give permissions tap on 'Change Settings' button" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil];
[alertController addAction:cancelAction];
UIAlertAction *settingsAction = [UIAlertAction actionWithTitle:@"Change Settings" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
}];
[alertController addAction:settingsAction];
[[UIApplication sharedApplication].keyWindow.rootViewController presentViewController:alertController animated:YES completion:nil];
}
}];
}
});
}
Common problem 1: Some users complain that the app doesn't show an alert after doing the above-mentioned changes in the info.plist
file.
Solution: For testing try to change Bundle Identifier
from the project file to something else, clean and rebuild the app. If it started working then everything is fine, rename it back.
Common Problem 2: There is some specific case when fetch results are not updated (and the views which used images from those fetch requests still empty accordingly) when the app gets permissions to photos, while running as it was promised in the documentation.
Actually it happens when we use WRONG code like this:
- (void)viewDidLoad {
if ([PHPhotoLibrary authorizationStatus] != PHAuthorizationStatusAuthorized)
{
//Reloading some view which needs photos
[self reloadCollectionView];
// ...
} else {
[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
if (status == PHAuthorizationStatusAuthorized)
[self reloadCollectionView];
// ...
}];
}
// ...
}
In this case, if the user denied giving permissions on viewDidLoad
then jumped to settings, allowed and jumped back to the the app, views will not be refreshed because [self reloadCollectionView]
and fetch requests were not sent.
Solution: We just have to call [self reloadCollectionView]
and do other fetch requests before requiring authorization like this:
- (void)viewDidLoad {
//Reloading some view which needs photos
[self reloadCollectionView];
if ([PHPhotoLibrary authorizationStatus] != PHAuthorizationStatusAuthorized)
{
// ...
}