アラートにいろいろなアクションを追加する
UIAlertControllerクラスのアラートには、複数のアクション、つまりボタンを付加することができます。そのために特別な操作は必要ありません。上の例で見たようにUIAlertActionのオブジェクトを作って、それをUIAlertControllerのaddActionメソッドで追加していけばよいのです。
ここでは新しい情報として、アクションには3種類のスタイルがあることを示しておきましょう。すでに上で使った.defaultに加え、.destructiveと.cancelがあります。
.destructiveは「破壊的」といった意味ですが、このタイプのボタンをタップするとアラートが粉々になるということではありません。これは情報を削除するとか、登録を解除するといった、後戻りできない処理を起動するボタンとして使うためのスタイルです。以前のiOSでは、他とは違う文字の色で表示されていましたが、現バージョンでは見た目で区別することは難しくなっています。もはや過去との互換性を確保するためのスタイルと考えた方がいいかもしれません。
.cancelは、文字どおりキャンセルボタンのためのものですが、ボタンのタイトルは自由に設定できます。ここでは「キャンセル」としています。このタイプのボタンのタイトルは、ほかより少し太い文字で表示されます。
プログラムを実行してみましょう。上の例では1つだけだったアラートのボタンが3つになっています。
そのぶん、アラートの面積が増えて、デフォルトで付いてくる曇りガラス効果がよりはっきりと認識できるでしょう。
アラートのアクションで画像のコンテントモードを変更する
ここまでに示したアクションの例では、UIAlertActionのオブジェクトを作る際に、handlerのパラメータには、すべてnilを指定していました。これは、そのボタンをタップしても何も起こらない(アラートを閉じるだけ)ことを意味しています。逆に言えば、ユーザーのボタン操作に対してどのような処理を実行すべきかを、このhandlerとして与えればいいわけです。このhandlerとして渡せるのは、Swiftのクロージャ(無名のファンクション)です。その場に、{}に包んで書くこともできますし、クロージャを代入した変数を指定することも可能です。ここでは後者の方法で、ボタン操作に対する処理を記述してみることにします。
もちろん、その前にボタン操作で何を実行するのかを考えなければなりません。この例では、ビューコントローラーのビューとして表示している表紙画像のコンテントモードを変更してみることにしましょう。このコンテントモードは、大きさや縦横比の異なるビューに別のビューをはめ込む際に、どのように拡大/縮小するのか、アスペクト比は維持するのかどうか、といったことを指示するためのものでした。
すでに見たように、表紙画像を表示するためのイメージビューは、viewDidLoadメソッドの中でセットアップしていました。このイメージビューのコンテントモードを、後から別のメソッドで変更したいので、まずイメージビューimgViewをviewDidLoadメソッドの外に出し、このビューコントローラーのプロパティとして定義することにします。
次に、ジェスチャーが認識されると呼び出されるlongPressDetectedメソッドの中で、アクションに対する処理を実行するクロージャを定義して、それをactionHandlerという定数に代入しておきます。
このハンドラーの外部的仕様は、タップされたボタンに対するアクションそのものを受け取って、何も返さない(Void)というものです。その中の処理では、どのボタンがタップされたのかをアクションのタイトルによって判断し、それに応じたコンテントモードを設定しています。
新たなアラートコントローラーには、「フィル」「アスペクトフィット」「アスペクトフィル」「センター」といった、4種類のコンテントモードに対するアクション(ボタン)を用意しています。それらのhandlerとしては、すべて上で定義したactionHandlerを設定しています。それにより、ユーザーがアラート上の「キャンセル」以外のボタンをタップすれば、その場でコンテントモードが切り替わるようになります。
このプログラムによって表示したアラートを見て見ましょう。
ここまでは上の例と実質的に何も変わらりません。「キャンセル」を含めて5つのボタンがアラート上に配置されています。これらのボタンを操作すると、その名前に応じたコンテントモードに切り替わり、表紙写真の表示モードが直ちに切り替わります。
アラートの外観をカスタマイズする
UIAlertControllerには、特に見た目をカスタマイズする機能は用意されていません。しかし、何らかの要求でアラートの見栄えを変更したいということもあるかもしれません。そのような要求の例として、アラートを不透明にしてその部分では下のビューがまったく見えなくなるようにしたい、というものを考えてみましょう。それは、アラートに含まれるビューの背景色を設定するという方法で実現できます。ただし、その効果を持つビューはかなり奥のほうにあります。言葉で表せば、アラートのビューの複数あるサブビューのうち最初のものが持つサブビューの最初のものの背景色を設定すればいい、ということになります。コードで書けば以下のようになります。これはそのビューの背景色を黄色に設定する場合です。
let alertContentView = alert.view.subviews.first!.subviews.first!
alertContentView.backgroundColor = .yellow
ただしこれだけだと、角が丸くない長方形の領域の背景色が変化するだけなので、そのビューのレイヤーの角の半径を設定することで元のアラートの形状に合わせることができます。
alertContentView.layer.cornerRadius = 15
以上の設定によって、アラートが持つ曇りガラス状の視覚効果の後ろに不透明のビューを挟み込むようなかたちになるため、ビューに設定した不透明な色の上に半透明な曇りガラスを重ねたような淡い色になります。
もう1つ別のカスタマイズ方法として、アラートの視覚効果そのものの、ブラー効果のスタイルを設定することもできます。その設定可能な視覚効果にアクセスするためには、ちょっとおまじないのようなコードが必要になります。言葉では説明し難いので、コードを見てください。
UIVisualEffectView.appearance(whenContainedInInstancesOf: [UIAlertController.classForCoder() as!
UIAppearanceContainer.Type]).effect = UIBlurEffect(style: .dark)
これはアラートの視覚効果を.darkに設定するものです。この結果、アラートは半透明の曇りガラス効果を保ったまま、そのスタイルが.darkに変更されました。
次回の予定
今回は、システムレベルで視覚効果ビューを利用したユーザーインターフェースの1つとして、アラートコントローラーを取り上げました。この機能にはそれほど奥行きがあるというわけではないので、次回はまた話題を転じることにしたいと思います。複数の画像を同時に表示する際に都合の良い、iOSならではのインターフェース機能に触れてみる予定です。