I have a settings view where the user can choose switch on or off the feature \'Export to Camera Roll\'
When the user switches it on for the first time (and
Since iOS 10 we also need to provide photo library usage description in info.plist
file which I described there. And then just use this code to make alert appear everytime we need:
- (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];
}
}];
}
});
}
Also there are some common cases when alert doesn't appear. To avoid copying I would like you to take a look at this answer.
I'm not sure if there is some build in method for this, but an easy way would be to use ALAssetsLibrary to pull some meaningless bit of information from the photo library when you turn the feature on. Then you can simply nullify what ever info you pulled, and you will have prompted the user for access to their photos.
The following code for example does nothing more than get the number of photos in the camera roll, but will be enough to trigger the permission prompt.
#import <AssetsLibrary/AssetsLibrary.h>
ALAssetsLibrary *lib = [[ALAssetsLibrary alloc] init];
[lib enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
NSLog(@"%zd", [group numberOfAssets]);
} failureBlock:^(NSError *error) {
if (error.code == ALAssetsLibraryAccessUserDeniedError) {
NSLog(@"user denied access, code: %zd", error.code);
} else {
NSLog(@"Other error code: %zd", error.code);
}
}];
EDIT: Just stumbled across this, below is how you can check the authorization status of your applications access to photo albums.
ALAuthorizationStatus status = [ALAssetsLibrary authorizationStatus];
if (status != ALAuthorizationStatusAuthorized) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Attention" message:@"Please give this app permission to access your photo library in your settings app!" delegate:nil cancelButtonTitle:@"Close" otherButtonTitles:nil, nil];
[alert show];
}
Since iOS 8 with Photos framework use:
Swift 3.0:
PHPhotoLibrary.requestAuthorization { status in
switch status {
case .authorized:
<#your code#>
case .restricted:
<#your code#>
case .denied:
<#your code#>
default:
// place for .notDetermined - in this callback status is already determined so should never get here
break
}
}
Objective-C:
[PHPhotoLibrary requestAuthorization:^(PHAuthorizationStatus status) {
switch (status) {
case PHAuthorizationStatusAuthorized:
<#your code#>
break;
case PHAuthorizationStatusRestricted:
<#your code#>
break;
case PHAuthorizationStatusDenied:
<#your code#>
break;
default:
break;
}
}];
Important note from documentation:
This method always returns immediately. If the user has previously granted or denied photo library access permission, it executes the handler block when called; otherwise, it displays an alert and executes the block only after the user has responded to the alert.
The first time the user tries to write to camera roll on ios 6 he/she is automatically asked for permission. You don't have to add extra code (before that the authorisationstatus is ALAuthorizationStatusNotDetermined ).
If the user denies the first time you cannot ask again (as far as I know). The user has to manually change that app specific setting in the settings->privacy-> photos section.
There is one other option and that is that it the user cannot give permission due other restrictions like parental control, in that case the status is ALAuthorizationStatusRestricted
Swift:
import AssetsLibrary
var status:ALAuthorizationStatus = ALAssetsLibrary.authorizationStatus()
if status != ALAuthorizationStatus.Authorized{
println("User has not given authorization for the camera roll")
}
iOS 9.2.1, Xcode 7.2.1, ARC enabled
'ALAuthorizationStatus' is deprecated: first deprecated in iOS 9.0 - Use PHAuthorizationStatus in the Photos framework instead
Please see this post for an updated solution:
Determine if the access to photo library is set or not - PHPhotoLibrary (iOS 8)
Key notes:
ALAuthorizationStatus
and PHAuthorizationStatus
.The easiest is to do...
if ([PHPhotoLibrary class])
{
//Use the Photos framework
}
else
{
//Use the Asset Library framework
}
You will need to decide which media collection you want to use as your source, this is dictated by the device that your app. will run on and which version of OS it is using.
You might want to direct the user to settings if the authorization is denied by user.