iOS 7 以降の UIAlertView カスタマイズ代替について考える
iOS 7 から UIAlertView - addSubView
が無効になった。従来はこのメソッドを利用して UI を拡張していた (方法については前に書いたこちらの記事を参照のこと) のだけど、それはもうかなわない。というわけで代替案を検討してみる。
UIAlertView が標準で提供しているカスタマイズ機能
iOS 5 から UIAlertView
は標準でカスタマイズ機能を提供している。alertViewStyle
プロパティに UIAlertViewStyle
列挙体の値を指定することで UI を切り替えられる。
UIAlertViewStyle | モード |
---|---|
UIAlertViewStyleDefault | 標準のアラート。alertViewStyle プロパティの規定値。 |
UIAlertViewStyleSecureTextInput | 単一のテキスト フィールド付きアラート。入力内容を隠してくれるので、パスワードなどに向く。App Store の認証などでも、お馴染み。 |
UIAlertViewStylePlainTextInput | 単一のテキスト フィールド付きアラート。 |
UIAlertViewStyleLoginAndPasswordInput | 2 段のテキスト フィールド付きアラート。ログイン時の User/Pass 入力に向く。2 段目のテキスト フィールドは入力内容を隠すタイプ。 |
以下はこれらを表示したところ。
こんな感じで利用する。
/**
* アラートを表示します。
*/
- (void)showAlert
{
UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"Title"
message:@"Please enter a value"
delegate:self
cancelButtonTitle:nil
otherButtonTitles:@"OK", nil];
alert.delegate = self;
alert.alertViewStyle = UIAlertViewStyleSecureTextInput;
[alert show];
}
/**
* アラート上のボタンがクリックされた時に発生します。
*
* @param alertView アラート。
* @param buttonIndex クリックされたボタンのインデックス。
*/
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if( buttonIndex == alertView.cancelButtonIndex ) { return; }
NSString* textValue = [alertView textFieldAtIndex:0] text];
if( [textValue length] > 0 )
{
// 入力内容を利用した処理
}
}
textFieldAtIndex
にテキスト フィールドのインデックス値を指定することで内容を参照可能。インデックス値は UIAlertViewStyleSecureTextInput
と UIAlertViewStylePlainTextInput
はテキスト フィールドが単体なので常に 0
、UIAlertViewStyleLoginAndPasswordInput
なら Login が 0
、Password は 1
となる。
テキスト入力ならこれらで十分。動作環境としても iOS 5 なら十分ではなかろうか。
進捗通知
モーダル実行される処理で時間がかかりそうなものは開始から終了までの進捗が表示されると親切。あまりに処理時間が長い場合は途中でキャンセルしたくなるかもしれない。
こうした要求へ応えるため以前は UIAlertView
へ UIProgressView
や UIActivityIndicatorView
を追加して進捗通知しつつキャンセル ボタンによる中断をサポートしていた。代替としては UIAlertView
を利用するなら進捗通知は message
プロパティでおこなう。更新を反映するために UIAlertView
のインスタンスをクラス単位で保持して進捗にあわせて message
プロパティを更新してゆくことになるだろう。
SVProgressHUD や MBProgressHUD を検討するのもよい。
これらはグラフによる進捗表示やインジケータによる待機通知、簡単なポップアップ メッセージの表示機能を提供してくれる。キャンセル ボタン相当の UI は提供されないため中断はタッチ操作をハンドリングするなどの工夫が必要。
どちらもライセンスは MIT。SVProgressHUD については使用リソースの関係で Glyphish icons についての記載があるが、そのままアプリへ組み込む分には問題ないだろう。
その他
これ以外の機能で UIAlertView
をカスタマイズしていたものについては素直に UIViewContrller
を利用したほうがよい。
ただしユーザーの操作するコントロールが少ないと画面として用意することがムダに感じられるかも。その場合は元の画面やアプリ全体の設定画面に統合することを検討してみる。例えば Amazon の Kindle アプリ的なタッチ操作で表示の切り替わるツールバーなどは実装も容易で使い勝手もよいと思う。
最近は画面にかぶさる形式のメニューで面白いものを見るようになった。これらも代替としてよいかもしれない。Cocoa Controls を sidebar や menu などで検索すればそういうコントロールがたくさん見つかる。有名なものだと以下になるだろうか。
- gotosleep/JASidePanels Facebook や Path 風のサイドバー メニュー
- levey/AwesomeMenu Path 2.0 以降で採用されているリング状に展開するメニュー
どちらもライセンスは MIT。見た目と使い勝手もよい。難点があるとすれば実装がすこし大掛かりになることや初見のユーザーが戸惑いそうなことぐらいか。
まとめると
- 通知や単純なテキスト入力なら標準の
UIAlertView
- 構成が複雑そうなら
UIViewController
- 目的やライセンスがアプリに合致するならサード パーティ製ライブラリも検討
こんな感じかな。凡庸ではあるが現実的にはこのあたりへ落ち着くのではなかろうか。