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

ほかのビューの上に重ねて表示可能なポップオーバーを出現させる

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

2018年02月12日 18時45分

ポップオーバーするテーブルビューに都市名を表示する

 ここからはポップオーバーの利用方法の話になりますが、今回はポップオーバーするテーブルビューに世界主要国の首都の名前をメニューとして表示し、最終的にはそこから選んだ都市の地図をベースのビューに表示することにします。

 まずは、テーブルビューの中身を表示するために、新たなクラスMenuViewControllerを定義しましょう。もちろんUITableViewControllerのサブクラスです。首都名は、とりあえず5つをcapitalsという文字列の配列として定義しました。これらをテーブルビューの各行に表示するよう、最小限のメソッドも実装します。

テーブルビューに内容を表示してメニュー的に利用するため、独自のクラスMenuViewControllerを定義します。とりあえず5カ国の首都の名前を配列として用意し、テーブルビューから選べるようにしてみましょう

 元のDetaillViewControllerの方は、ほとんどそのままでいいのですが、2カ所だけ変更しました。1つはポップオーバーを表示するためのボタンの名前で、それを「首都」としています。

ベースとなるビューを含むDetailViewControllerのほうでは、ナビゲーションバーのボタンの名前を「首都」に変更し、そのボタンがタップされたときにポップオーバーとして表示するビューコントローラーを、上で定義したMenuViewControllerに変更しています

 もう1つは、そのボタンがタップされたとき、ポップオーバーとして表示するビューコントローラーの種類です。上の例ではデフォルトのテーブルビューコントローラーでしtくぁあ、それを上で定義したMenuViewControllerのクラスに変更します。そうしないと、いつまでも空のテーブルビューしか表示されません。

 このプログラムを動かして、ナビゲーションバー上の「首都」ボタンをタップすると、テーブルビューによるメニューが開き、配列として定義した首都の名前が表示されます。

ここまでの変更で、ナビゲーションバー上の「首都」ボタンをタップすると、都市の名前を選択可能なテーブルビューがポップオーバーとして表示されるようになりました。まだ選択しても何も起こりません

 それ以上は、まだプログラムしていないので、ここでどれかの首都を選んでもその名前がハイライトされる以外は何の反応もありません。ポップオーバーは、もう一度「首都」ボタンをタップすれば閉じることができます。

ポップオーバーからベースのビューコントローラーに情報を伝達する

 次に、テーブルビューによって作成し、ポップオーバーとして表示したメニューから選んだ項目の情報を、ベースのビューコントローラーに伝達する方法を考えてみましょう。

 ポップオーバーとして表示されるテーブルビューは、自分がどうやって誰によって表示されたのかを知りません。そのどこの誰だか知らないビューコントローラーに情報を伝達するために、前回と同様にプロトコルによるデリゲートを定義して使うことにしました。仕組みは前回とまったく同じなので、詳しい説明は省きます。まずは、MenuSelectionDelegateというプロトコルを定義し、MenuViewControllerに、その型のdelegateという変数を用意しておきます。

テーブルビューから選択した都市の名前を、ベースとなるビューコントローラー側に伝達するために、今回もプロトコルによるデリゲートを利用します

 テーブルビュー上の都市名が選択されたら、デリゲートのmenuSelectedメソッドをその都市名を指定して呼び出します。また、dismissメソッドによってテーブルビューの自身の表示、つまりポップオーバーを閉じています。

テーブルビューのセルを選択すると、そこに表示されている名前を引数として、デリゲートのmenuSelectedメソッドを呼び出すようにします。呼び出された側では、その名前をビューに表示するためのラベルを用意しています

 一方のDetailViewControllerは、上で定義したプロトコルに準拠させます。また、都市名を表示するためのラベルを用意して画面の中央に配置しています。

ラベルは画面の中央に配置しています。この段階では受け取った名前の文字列をラベルのテキストとして設定しているだけです

 さらに、ナビゲーションバー上のボタンがタップされた際には、その場で作成したMenuViewControllerのデリゲートに自分自身を代入して誰がテーブルビューを表示したのかを明らかにしています。デリゲートとして呼び出されるmenuSelectedメソッドも実装して、渡された都市名の文字列をラベルのテキストとして表示します。

 このプログラムを実行して、「首都」ボタンをタップすると、都市名のメニューが表示されます。

「首都」ボタンをタップすると、都市名のメニューが表示されるところまでは、これまでと変わりません。こんどは選択に対する反応があります

 ここまでは、前と同じですが、こんどは選択直後にメニューのテーブルビューはポップオーバーごと消え、ベースのビューのほぼ中央に、選択した都市名が表示されます。

この段階での反応は、ポップオーバーメニューから選んだ都市名が、ベースのビューの中央に表示されるだけです。ラベルが左にずれて見えるのは、テキストを左寄せで表示しているからです

 これで、ポップオーバーをメニューとして利用し、その選択結果がポップオーバーを出現させたほうのビューコントローラーに伝達できることが確かめられました。

メニューから選んだ都市の地図を表示する

 選んだ都市名を文字列として表示したのは情報伝達を確かめるためだけです。ここからは、その都市の地図を表示するようにプログラムを追加していきましょう。それもMapKitを使えば簡単です。都市名からジオコーディングによって場所を割り出すのも以前に示したようにそれほど難しくありません。しかし、今回はそこは重要ではないので、簡略化のため、あらかじめ位置を記憶しておくことにしました。そのために、Capitalという構造体を定義して都市名と位置(CLLocationCoordinate2D)をまとめて1つのオブジェクトに記録します。

選んだ都市の周辺の地図を表示するために、capitals配列は都市名とその都市のロケーションを緯度と経度で指定したものを組み合わせたオブジェクトの配列にしました

 これまで単なる文字列の配列だったcapitalsは、Capitalの配列に改め、都市名と、その緯度、経度から作った座標オブジェクトをセットにして作成しておきます。

 その配列の型の変更にともない、ほかの部分でもいくつか変更が必要になります。まず、デリゲートのmenuSelectedメソッドの引数の型をStringからCapitalに変更します。また、テーブルビューを作成する際のcellForRowAtメソッドの中では、セルのテキストラベルとして、配列の要素そのままではなく、要素のnameプロパティの値をセットするように変更します。

配列の型を変更したので、テーブルビューのセルの中身を表示するためのメソッドでは、配列要素のnameプロパティをセルのテキストにセットするように変更します

 実際に地図を表示するDetailViewControllerの変更は、意外に少なく感じられるでしょう。まず、当然ながらラベルの代わりにマップビューのオブジェクトを作成し、それをこのコントローラーのビュー全体として設定します。

ベースとなるDetailViewControllerでは、ビュー全体をマップビューに入れ替えて指定された都市周辺の地図の表示に備えます

 あとは、デリゲートメソッドのmenuSelectedの中で、実際に地図に表示する領域を設定するだけです。

実際の地図の表示はかなり簡単です。渡されたCapital型の引数のlocationプロパティから緯度と経度による位置情報を取り出し、領域の大きさは5km×5kmに固定してリージョンを作成し、マップビューにセットするだけです

 これについても以前にMapKitを取り上げた時に説明していますので詳しくは述べません。引数として渡されてきたCapitalオブジェクトのlocationプロパティと、5km四方の大きさを指定してリージョンを作成し、それをマップビューにセットしています。

 このプログラムを起動すると、ベースとなるビューには何も設定していない初期状態の地図が表示されます。

プログラムを起動すると、位置や領域をまったく指定しないデフォルトの地図が表示されます。初期の表示位置を指定するようにしてもいいでしょう

 この表示は、ユーザーの環境によって異なる可能性があります。ここから「首都」ボタンをタップして都市を選びます。ここでは「ロンドン」を選んでみました。

「首都」ボタンをタップすると、これまでと同様にポップオーバーするテーブルビューのメニューから都市名を選択することができます。「ロンドン」を選んでみました

 その結果、プレイグラウンド画面にはロンドン近辺の地図が表示されます。

「メニューから都市を選ぶとポップオーバーが閉じて、ベースのビューコントローラーのビューには、選んだ都市周辺の地図が表示されます

次回の予定

 今回は、ポップオーバープレゼンテーションコントローラーを利用した「メニュー選択→内容を詳しく表示」というパターンを使って、都市名を選んで地図を表示するアプリに仕立てました。それはほんの一例であって、このパターンは、アイディア次第でどのようなものにも応用できるでしょう。次回からは、複数のビューコントローラーの扱いというテーマから離れて、また少し地味なiOSならではのデータの扱いを取り上げる予定です。

mobileASCII.jp TOPページへ

mobile ASCII

Access Rankingアクセスランキング