iOS Tips #6 写真のアクセス制限
前回のiOS Tips #5 位置情報サービスのアクセス制限に引き続き、今回はiOSで写真へのアクセス制限の実装方法を紹介したいと思います。位置情報サービスと同様、アプリから写真にアクセスする場合の挙動を理解することで、安心して使ってもらえるアプリを構築することができます。
では早速サンプルを作ってみましょう。今回は以下の環境を前提に説明します。
Mac OS X 10.8 Moutain lion
Xcode 4.6.2
iOS SDK 6.1
iPhone 5
プロジェクトの作成
まずは、XcodeよりSingle View Applicationを選択し、以下の内容でプロジェクトを作成しましょう。
項目 | 設定値 |
---|---|
Product Name | PhotoAccessSample |
Organization Name | 自分の名前(サンプルなのでテキトー) |
Company Identifier | 会社名(サンプルなのでテキトー) |
Class Prefix | なし |
Devices | iPhone |
Use Storyboards | チェックする(ストーリーボードを使用) |
Use Automatic Reference Counting | チェックする(ARC有効) |
Include Unit Tests | チェックしない(unit testのターゲットを含まない) |
AssetLibrary.frameworkの追加
写真へのアクセス制限を実装するのにAssetLibrary.frameworkを使用するのでPhotoAccessSampleプロジェクトにAssetLibrary.frameworkを追加しましょう。
ViewControllerの実装
今回は写真を利用するロジックをViewControllerに実装します。まずは以下のように実装してください。
ViewController.m
#import "ViewController.h" #import <AssetsLibrary/AssetsLibrary.h> @interface ViewController () @end @implementation ViewController #pragma mark - UIViewController lifecicle event methods - (void)viewDidLoad { [super viewDidLoad]; } - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; // 写真へのアクセスを開始する [self startUsePicture]; } #pragma mark - Private methods - (void)startUsePicture { // このアプリの写真への認証状態を取得する ALAuthorizationStatus status = [ALAssetsLibrary authorizationStatus]; switch (status) { case ALAuthorizationStatusAuthorized: // 写真へのアクセスが許可されている case ALAuthorizationStatusNotDetermined: // 写真へのアクセスを許可するか選択されていない { __block NSMutableArray *groups = [NSMutableArray array]; ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init]; [library enumerateGroupsWithTypes:ALAssetsGroupAll usingBlock:^(ALAssetsGroup *group, BOOL *stop) { if (group) { // グループ名を配列に追加 [groups addObject:[group valueForProperty:ALAssetsGroupPropertyName]]; } else { // 端末のアルバム名を一覧に表示する dispatch_async(dispatch_get_main_queue(), ^{ UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"確認" message:[NSString stringWithFormat: @"この端末のアルバム\n%@", [groups componentsJoinedByString:@"\n"]] delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; [alertView show]; }); } } failureBlock:^(NSError *error) { dispatch_async(dispatch_get_main_queue(), ^{ UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"エラー" message:@"このアプリでの写真へのアクセスを許可されなかったよ!" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; [alertView show]; }); }]; } break; case ALAuthorizationStatusRestricted: // 設定 > 一般 > 機能制限で利用が制限されている { UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"エラー" message:@"設定 > 一般 > 機能制限で利用が制限されてるよ!" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; [alertView show]; } break; case ALAuthorizationStatusDenied: // 設定 > プライバシー > 写真で利用が制限されている { UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"エラー" message:@"設定 > プライバシー > 写真で利用が制限されてるよ!" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; [alertView show]; } break; default: break; } } @end
写真への認証状態を取得する
写真の利用を開始するまえに、アプリが写真へのアクセスが許可されているかを調べます。これにはALAssetsLibraryクラスのクラスメソッド「+ (ALAuthorizationStatus)authorizationStatus(ViewController.m:30行目)」を使用します。このメソッドを実行するとALAuthorizationStatusで定義される以下のステータスが返されます。
設定値 | 説明 |
---|---|
ALAuthorizationStatusNotDetermined | アプリ起動後、写真へのアクセスを許可するかまだ選択されていない状態 |
ALAuthorizationStatusRestricted | 設定 > 一般 > 機能制限により写真の利用が制限されている状態 |
ALAuthorizationStatusDenied | ユーザーがこのアプリでの写真へのアクセスを許可していない状態 |
ALAuthorizationStatusAuthorized | ユーザーがこのアプリでの写真へのアクセスを許可している状態 |
名前が違うだけで位置情報サービスと同じような内容ですね。
ALAuthorizationStatusRestricted
ユーザーが機能制限(ペアレントコントロール)により意図的に写真の利用を制限している場合にこのステータスが返されます。この場合、ユーザーによって機能制限を解除してもらわないと写真を利用することができません。機能制限の設定は[設定 > 一般 > 機能制限]で行います。
ALAuthorizationStatusDenied
ユーザーが意図的にこのアプリでの写真へのアクセスを許可していない場合はこのステータスが返されます(ダイアログで「許可しない」を選択した場合など)。この設定は[設定 > プライバシー > 写真]から行います。
写真の利用を開始する
+ (ALAuthorizationStatus)authorizationStatusでALAuthorizationStatusNotDeterminedかALAuthorizationStatusAuthorizedが返された場合は写真の利用開始を試みます(ViewController.m:38〜70行目)。ここが重要なのですが、ALAssetsLibraryクラスで定義されるメソッド「- (void)enumerateGroupsWithTypes:(ALAssetsGroupType)types usingBlock:(ALAssetsLibraryGroupsEnumerationResultsBlock)enumerationBlock failureBlock:(ALAssetsLibraryAccessFailureBlock)failureBlock」です(なっが)。最初に説明したダイアログですが、実はこのメソッドが初めて実行されるタイミングで表示されます。これも位置情報サービスと同様ですね。
写真へのアクセスが許可されると、enumerationBlockで設定した処理が実行されます。ダイアログで「許可しない」が選択されると、failureBlockが実行されます。
iOS6以降:確認ダイアログに独自のメッセージを追加する
iOS6からはXxx-Info.plistにNSPhotoLibraryUsageDescriptionを追加することで、確認ダイアログに独自のメッセージを追加することができます。
UIImagePickerControllerを使用する場合
UIImagePickerControllerを使うはenumerationBlockの処理を以下のように変更するだけでOKです。
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init]; [library enumerateGroupsWithTypes:ALAssetsGroupAll usingBlock:^(ALAssetsGroup *group, BOOL *stop) { UIImagePickerController *picker = [[UIImagePickerController alloc] init]; picker.delegate = self; [self presentViewController:picker animated:YES completion:nil]; } failureBlock:^(NSError *error) { ・・・ }];
まとめ
如何でしょうか?位置情報サービスを利用するときと基本的には変わらないですね! 次回は連絡先について書きたいと思います。