24/7 twenty-four seven

iOS/OS X application programing topics.

iOS 7のエンタープライズ向け新機能 Guided Access(アクセスガイド)のカスタマイズ

20131108031636 20131108031636

アクセスガイドとは

iOS 6から導入された機能にアクセスガイドがあります。
これは一時的にホームボタンを無効にして1つのアプリケーションしか使えないようにしたり(クラッシュしても自動的にそのアプリケーションが再起動する)、タッチ操作を部分的に無効にして触ってほしくないボタンなどを使えなくするなど、いわゆるキオスクモードを実現できる機能です。

展覧会や店舗などでナビゲーション端末として一般のひとに貸し出して使ってもらう場合などに利用されます。


iOS 7では上記の機能に加え、アプリケーションごとに制限を定義できるようになりました。

これによって、これまでの機能でできる制限だと、アプリケーションの作りによってはボタンの位置などでうまく制限がかけられなかったりすることがありましたが、その問題がアプリケーションの対応によって解決されます。
特に企業向けのアプリケーションを提供しているところにとっては魅力的な改善だと思います。

iOS 7から追加されたアクセスガイドのカスタマイズ

アプリケーション側で対応するにはiOS 7から追加されたAPI`UIGuidedAccessRestrictionDelegate`を使います。
`UIGuidedAccessRestrictionDelegate`のメソッドを`UIApplicationDelegate`に実装すると必要に応じてシステムから呼び出されます。


`UIGuidedAccessRestrictionDelegate`の定義は次のようになります。

@required
- (NSArray *)guidedAccessRestrictionIdentifiers;
- (void)guidedAccessRestrictionWithIdentifier:(NSString *)restrictionIdentifier didChangeState:(UIGuidedAccessRestrictionState)newRestrictionState;
- (NSString *)textForGuidedAccessRestrictionWithIdentifier:(NSString *)restrictionIdentifier;

@optional
- (NSString *)detailTextForGuidedAccessRestrictionWithIdentifier:(NSString *)restrictionIdentifier;

@end


このうち、`detailTextForGuidedAccessRestrictionWithIdentifier:`以外のメソッドはすべて実装する必要があります。

`guidedAccessRestrictionIdentifiers`ではアプリケーションで独自に定義した制限を示す識別子を文字列の配列で返します。
それぞれが区別できればどのようなものでも構いません。

例えば、これまでの例と同様に、設定画面へのアクセス、記事のシェア、および削除を禁止したいとします。
それぞれに適当な識別子を決めて下記のようなコードになります。

- (NSArray *)guidedAccessRestrictionIdentifiers
{
    return @[@"allow-settings", @"allow-share", @"allow-delete"];
}


次にそれぞれの制限に対応する簡潔な説明を定義します。

- (NSString *)textForGuidedAccessRestrictionWithIdentifier:(NSString *)restrictionIdentifier
{
    if ([restrictionIdentifier isEqualToString:@"allow-settings"]) {
        return NSLocalizedString(@"Access Settings", nil);
    } else if ([restrictionIdentifier isEqualToString:@"allow-share"]) {
        return NSLocalizedString(@"Allow Share", nil);
    } else if ([restrictionIdentifier isEqualToString:@"allow-delete"]) {
        return NSLocalizedString(@"Allow Delete", nil);
    }
    
    return nil;
}


必要なら詳しい説明を追加します。

- (NSString *)detailTextForGuidedAccessRestrictionWithIdentifier:(NSString *)restrictionIdentifier
{
    if ([restrictionIdentifier isEqualToString:@"allow-settings"]) {
        return NSLocalizedString(@"Allow change settings.", nil);
    } else if ([restrictionIdentifier isEqualToString:@"allow-share"]) {
        return NSLocalizedString(@"Allow share link to other services.", nil);
    } else if ([restrictionIdentifier isEqualToString:@"allow-share"]) {
        return NSLocalizedString(@"Allow delete entries.", nil);
    }
    
    return nil;
}


上記で定義した制限の有効・無効、あるいはアクセスガイド自体のオン・オフが切り替わったときには下記のデリゲートメソッドが呼ばれるので、そこでボタンを消したり、UIを更新したりします。
制限が有効になったのか無効になったのかの判断は`newRestrictionState`の値を使います。
アクセスガイド自体がオフになったときは制限を識別子についてこのメソッドがそれぞれ呼ばれて、`newRestrictionState`の値は`UIGuidedAccessRestrictionStateAllow`になっています。

- (void)guidedAccessRestrictionWithIdentifier:(NSString *)restrictionIdentifier didChangeState:(UIGuidedAccessRestrictionState)newRestrictionState
{
    if ([restrictionIdentifier isEqualToString:@"allow-settings"]) {
        if (newRestrictionState == UIGuidedAccessRestrictionStateAllow) {
            // Settingsボタンを表示する
        } else if (newRestrictionState == UIGuidedAccessRestrictionStateDeny) {
            // Settingsボタンを消す
        }
    } else if ([restrictionIdentifier isEqualToString:@"allow-share"]) {
        if (newRestrictionState == UIGuidedAccessRestrictionStateAllow) {
            // シェアボタンを表示する
        } else if (newRestrictionState == UIGuidedAccessRestrictionStateDeny) {
            // シェアボタンを消す
        }
    } else if ([restrictionIdentifier isEqualToString:@"allow-delete"]) {
        if (newRestrictionState == UIGuidedAccessRestrictionStateAllow) {
            // 削除機能を有効にする
        } else if (newRestrictionState == UIGuidedAccessRestrictionStateDeny) {
            // 削除機能を無効にする
        }
    }
}


また、いつでも`UIGuidedAccessRestrictionStateForIdentifier()`という関数(iOS 7から)を使って任意の制限が有効かどうかを調べることができます。

if (UIGuidedAccessRestrictionStateForIdentifier(@"allow-settings") == UIGuidedAccessRestrictionStateDeny) {
    // 設定画面へのアクセスが無効になっている場合の処理
}


アクセスガイド自体が有効か無効かは`UIAccessibilityIsGuidedAccessEnabled()`という関数でわかりますし、アクセスガイドの状態が変わったときに`UIAccessibilityGuidedAccessStatusDidChangeNotification`の通知を受けることもできます。(どちらもiOS 6から)。


ここまで記述した状態でアクセスガイドの画面を表示して「オプション」で表示される項目が次のようになります。

20131108031636


赤で示した部分が先ほど追加したアプリケーション独自の制限になります。
スイッチがオンの場合は許可、オフの場合は制限をかけるという意味になります。

上記の状態では記事の共有と削除を禁止し、設定画面へのアクセスは許可するということになります。
この状態でアクセスガイドを再開した場合、状態変化のデリゲートメソッドが呼ばれるので制限の変更に応じて適宜UIの更新や対応する処理をします。


以上です。いかがでしょうか。
特にビジネス用途で使われることを想定したアプリケーションでは強力に機能するのではないでしょうか。