Swift Playgroundsで学ぶiOSプログラミング

アラート画面に画像を表示する裏技をプログラミング

文●柴田文彦 編集●吉田ヒロ

2017年04月03日 17時00分

選択に対応するメソッドを実装する

 これまでに登場した、テーブルビューに表示する内容を設定するメソッドは、こちら(テーブルビュー側)から呼び出すのではなく、すべてあちら(iOS側)から呼び出してもらうものでした。そうしたメソッドをテーブルビューコントローラー内に用意しておくと、必要なタイミングでシステムが呼び出してくれるという仕組みになっていました。

 もしかすると、その仕組みに対しては、完全には腑に落ちないものを感じた人もいるかもしれません。別の方法でも可能ではないかと思われるからです。しかし、今回のようにユーザーがテーブルビューを操作したことを伝えるためのメソッドの場合には、システムから呼び出してもらう以外に方法がないことは納得できるでしょう。ユーザーが画面にタッチしたことに応答するのは、まずはシステムの責任だからです。iOSのシステムは、そのあとにそれがどのビューに向けられたものかに応じて、該当するコントローラーのメソッドを呼び出すようになっています。

 テーブルビューの1つの行が、タッチによって選択されたことを知らせるメソッドの一般形は、以下のようになっています。

optional func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)

 名前そのものはtableViewで始まっていて、これまでに使ってきた内容表示のためのメソッドと似ていますが、決め手はdidSelectRowAtという部分です。これは「その行が選択された」といった意味ですが、それがどの行かは、そのあとの引数indexPathによって示されます。

 今回は、前々回に作成した果物の画像と名前を表示するテーブルビューのプログラムをそのまま使って、そこにコードを書き加えていくことにします。とりあえず、上のメソッドを中身は空のまま書き加えてみましょう。PGTVControllerの中に記述します。

前々回に作成した果物の名前と画像を表示するテーブルビューのプログラムに、行を選択すると呼ばれるメソッドを中身は空のまま書き加えました

 上の基本形のoptionalの部分をoverrideに変えて、後ろに{}を付ければ、とりあえず空のメソッドを実装することができます。このまま動かしてみましょう。動作は、このメソッドを実装する前と変わりませんが、テーブルビューの行にタッチすると、その部分が薄いグレーでハイライトされた表示になります。

行を選択すると呼ばれるメソッドの中身が空なので、動作はそれがないときと変わりません。ユーザーのタップによって選択された行のハイライト表示がそのまま残ります

 実はテーブルビューとしては、このようにタッチされた状態がいつまでも残るのは好ましくない動作だとされています。これによって、その行が何らかの目的で選択されているのと誤解されるからです。そこで、タッチされてハイライトされた状態は、すぐに解除してやる必要があります。これが、didSelectRowAtのメソッドの最初の仕事です。

 そのためには、渡されたtableViewオブジェクトのdeselectRow()というメソッドを使います。「指定した行の選択を解除する」ものです。どの行かは、引数at:としてindexPathをそのまま渡すことで指定します。もう1つの引数animated:では、アニメーションの有無を指定します。この場合は選択を解除するだけなので、アニメーションはなしということでfalseを与えています。以上のコードを書き加えてみましょう。

deselectRow()というメソッドを使って、選択されてハイライト表示になった行の選択状態を解除しています。この画像だけを見てもわかりませんが、実際に動かしてみると、テーブルビューの行にタップして選択状態にしても自動的にすぐに解除されます

 面白い変化は起きませんが、以前とは異なって、タッチして選択された行が、すぐに元の状態に戻ることが確認できます。

アラートを利用して、ユーザーがタップした行の果物の名前を表示するようにプログラムを書き加えました。果物の名前はfruits配列から得ることができます

選択された行の内容をアラートで表示する

 言うまでもなく、選択された行の選択を解除するだけでは、ほとんど何の意味もないプログラムのままです。ユーザーがその行を選択したことによって、最低でもその行に関する何らかの情報を表示することが必要でしょう。そのために、今回はアラートを使うことにします。アラートは、以前にウェブブラウザーを作成した際に開きたいURLを入力するために使いました。今回はユーザーから入力を受け取るわけではないので、そのときのアラートよりもむしろ単純です。

 アラートを表示するコードは、もちろんテーブルビューの行の選択を知らせるメソッドの中に書きます。アラートにはタイトルとメッセージを表示することができました。今回はメッセージは「ユーザーアクション」という固定の文字列とし、メッセージとして選択された行の内容を表示することにします。選択された行はindexPath.rowで知ることができます。その値をfruits配列のインデックスとして指定すれば、選択された行の果物の名前が得られます。それに「がタップされました。」という文字列を付け足したものをメッセージとしましょう。また、このアラートには「OK」ボタンを配置して閉じることができるようにします。

テーブルビューの行をタップすると、その行の果物の名前がメッセージの一部として表示されるようになりました。アラートは「OK」ボタンをタップして閉じます

 アラートの表示を試してみましょう。狙ったとおり、選択された行の果物の名前を知ることができるようになりました。

アラートに画像を追加する

 これで、ユーザーとテーブルビューのやり取りが、わずかながらプログラムの動作に反映されるようになってきました。ただ、アラートの表示として果物の名前がわかるだけではいかにも寂しいのは事実です。せっかくなら、テーブルビューの各行の左端に表示している画像を大きくしてアラートの中に表示したいと思った人も多いでしょう。

 ところが、ここで大きな障害にぶつかります。実はiOSのアラート(UIAlertController)自体には、画像を表示する機能はないのです。以前にURLの入力に使ったようなテキストフィールドは表示できても、画像を表示する機能は備わっていないのです。

 それでも、iOSアプリで画像付きのアラートを見たことがあるという人もいるでしょう。そう、アラートに画像を表示することは可能なのです。アラート自体にその機能が備わっていなくても、アラートを表示するための基本のビューに画像のビューをサブビューとして張り付けてやればいいのです。

 今回はアラートに画像を表示するのが本題ではないので、ざっとだけ説明しましょう。まず、張り付ける画像はテーブルビューの表示用に用意した画像ファイルを流用し、UIImageというクラスのオブジェクトとして作成します。次にその画像を含むビューをUIImageViewのオブジェクトとして作成します。その際には、CGRectというタイプで、ビューの中の画像の位置と大きさを同時に指定します。あとは、そうやって作成した画像を含むビューをアラートのビューに張り付けるだけです。アラートのビューには、UIAlertControllerのオブジェクトのviewプロパティを使って簡単にアクセスできます。1つのビューを別のビューに張り付けるのは、どんなビューにも備わっているaddView()メソッドが利用できます。

 以上のコードは、アラートを作成したあと、それを表示するpresent()メソッドの前の部分に書きます。もともとアラートには画像を表示する領域は確保されていないので、メッセージの後ろに8個の改行を付加して、スペースを確保するという原始的なことをやっています。

選択された果物の画像をアラート内に表示するようにプログラムを書き加えました。選択された行の果物の画像はpics配列から得ることができます。アラート自体のビューに画像のビューをサブビューとして張り付ける手法を使いました

 これを動かしてみると、アラートのメッセージの下に選択した行の果物の画像が表示されるようになります。用意した元の画像のサイズが128×128ピクセルだったのでここでは等倍で表示していますが、CGRectの設定次第でもっと大きくしたり、逆に小さくしたりすることも可能です。その場合は、やはりCGRectの設定で画像の位置も調整する必要があります。

テーブルビューの行をタップすると、その行の果物の名前を含むメッセージに加えてその画像が表示されるようになりました

次回の予定

 今回は、ユーザーがテーブルビューの行にタッチしたことを感知して、それに応じた表示をアラートを使って実現しました。これでだいぶアプリらしくなってきたものの、まだiOSアプリとしては何か重要なものが足りないと感じている人も多いでしょう。次回は、その部分を補って、iOSアプリならではの基本的な機能を実現していく予定です。

mobileASCII.jp TOPページへ

mobile ASCII

Access Rankingアクセスランキング