FPPopoverのメニュー選択後の処理を指定する
前節までで、SwiftでFPPopoverを使ってポップオーバーを表示するところまではできました。本節では、ポップオーバー内のメニューを選択した際に、選択したアイテムを取得する処理の実装について順を追って説明します。
デリゲートを定義する
連載第6回で説明した通り、ポップオーバー内のメニューはテーブルビューコントローラーです。テーブルのセルが選択された際に別の画面で何らかの処理を行う場合は、自分でデリゲートを定義して処理を行うことが一般的です。テーブルビューコントローラー側でデリゲートを作成しておき、セル選択時にデリゲートのメソッドを実行するようにします。ポップオーバーを出力するビューコントローラーでは、テーブルビューコントローラー側で作成したデリゲートを実装し、デリゲートのメソッド内の処理を記述しておきます。このようにしておくことで、セル選択→デリゲートのメソッドの呼び出し→ビューコントローラーでの処理の実行、という一連の動きを実装できます。デリゲートもメソッドも開発者が自由に作成できますので、任意の処理をアプリで実装できます。
作成するデリゲートのイメージは次の通りです。
サンプルでは、ポップオーバーのメニューを選択した際に、デリゲートを使って選択したアイテムをビューコントローラーに表示する処理を実装します。最初に利用するデリゲートをTableViewController.swift内に次のように定義します。
// デリゲートを定義 protocol didSelectItem : NSObjectProtocol { // 文字列を引数としたメソッドを定義 func selectItem(item:String) }
デリゲートの実体となるプロトコルは、NSObjectProtocolクラスを継承してTableViewController.swift内に定義します。その際に、セル選択時に呼ばれる文字列の引数を渡すselectItemメソッドも定義します。
この記述でデリゲートの定義ができました。
デリゲートを参照するプロパティを作成する
デリゲートの定義後、次のようにTableViewController.swift内にdelegateプロパティを設けて、外部からデリゲートを参照できるようにします。プロパティの定義は、変数の定義と同様に型にデリケートを指定して次のように行います。
class TableViewController: UITableViewController { // デリゲートを参照するプロパティ var delegate:didSelectItem? let kCellIdentifier = "CellIdentifier" var items : Array<String> = ["item1", "item2", "item3"]
デリゲートにアクセスするプロパティは、利用せずに空のままの可能性もありますので「?」をつけておきます。ここまででデリゲートを作成して利用する準備ができました。
デリゲートのメソッドを呼び出す
前項で作成したデリゲートのメソッドが、セルの選択時に実行されるようにします。メソッドの実態はデリゲートの実装先にありますので、実装先のメソッドが動くようにします。具体的には、TableViewController.swift内のテーブルのセルが選択された際に呼ばれるtableView(_:didSelectRowAtIndexPath:)メソッドの内部で、デリゲートの実装先のメソッドを呼び出します。
// セル画選択された際の処理 override func tableView(tableView: UITableView?, didSelectRowAtIndexPath indexPath:NSIndexPath) { // 選択したセルのテキスト var item : String = self.items[indexPath.row] // デリゲートを実装したオブジェクトがselectItem:メソッドを存在する場合のみ // 実装先のselectItem:メソッドを実行 if (self.delegate?.respondsToSelector("selectItem:")) != nil { // デリゲートの実装先のselectItem:メソッドを実行 delegate?.selectItem(item) } }
デリゲート実装先のメソッドを呼び出す際には、デリゲートを参照するプロパティdelegateを用いて「delegate?.メソッド」の形式で呼び出します。デリゲートが空である可能性も考慮して「?」をつけます。
さらにrespondsToSelectorメソッドで、実装先にデリゲートのメソッドが存在するかチェックします。メソッドが存在しない場合にアプリが落ちてしまうのを防ぐためです。
デリゲートを実装する
作成したデリゲートのメソッドをビューコントローラーで実装します。デリゲートの実装は、クラスの継承と同様にクラス名の後ろに記述します。
class ViewController: UIViewController, didSelectItem {
ViewControllerクラスの場合、既にUIViewControllerクラスを継承していますので、「,」で区切って実装するデリゲート名を記述します。
ViewControllerクラスにデリゲートを実装した後に、TableViewControllerクラスのdelegateプロパティをViewControllerクラス自身に向けてデリゲートの実装先を明確にします。サンプルでは、ポップオーバーのメニューとなるTableViewControllerクラスを初期化する段階で、delegateプロパティでデリゲートの実装先を指定します。具体的にはポップオーバーを呼び出す次の部分でデリゲートの指定を行います。
// ボタンを押した際の処理 func onPush(sender:UIButton) { // ポップオーバー内に表示するテーブルビューコントローラーを初期化 var tableViewController : TableViewController = TableViewController(nibName : nil, bundle : nil) // デリゲートを自分自身に指定 tableViewController.delegate = self // FPPopoverKeyboardResponsiveControllerを初期化 popover = FPPopoverKeyboardResponsiveController(viewController:tableViewController) as FPPopoverKeyboardResponsiveController ...中略... }
上記のように、ViewController.swift内でdelegateプロパティの指定をselfに指定することで、テーブルのセルを選択した際にViewController.swift内に記述したselectItemメソッドを呼び出せるようになります。
デリゲートのメソッドの処理を指定する
最後に、デリゲートのメソッドが実行された際に行われる処理を指定します。メソッド自体はデリゲートの定義の部分で作成していますので、同じメソッドを実装先であるViewController.swift内に記述します。
// デリゲートで定義されたメソッドを実装 func selectItem(item:String) { // メニューの選択されたセルの文字列を表示 label.text = item; // ポップオーバーを閉じる popover.dismissPopoverAnimated(true) }
デリゲートのメソッドの書式の通りにメソッドを記述して、メソッド内の処理を作成します。サンプルではInterfaceBuilderで画面に配置したラベルの表記をメソッドで渡された文字列にしています。ポップオーバーを閉じるdismissPopoverAnimatedメソッドは、FPPopoverControllerクラスのメソッドをSwiftの書式で記述したものです。
サンプルを実行すると、次の処理が確認できます。
まとめ
7回の連載を通して開発環境の設定からSwiftの基本的な文法、Objective-Cの資源の利用方法まで説明しました。本連載を通して、Swiftの記述の容易さや扱いやすさを実感してもらえたかと思います。記述が複雑でエラーの発生しやすいObjective-Cと比べて、Swiftではより少ない労力でより速くiOSアプリの開発が可能です。
また、画面の位置関係やデリゲート等のiOSアプリ開発で用いられる共通の概念については、Objective-Cのものを踏襲しており、Swiftから新しく覚えなければならないことはほぼありません。Objective-Cを使っている開発者にとってもSwiftへの移行は非常にやりやすくなっています。
Swiftの登場でiOSアプリの開発が格段に行いやすく、始めやすくなりました。このことは、スマホアプリの開発でよく言われる「アイディアを形にする」ことがより身近になったと言えます。Objective-Cですでにアプリ開発を始めている方はもちろん、これからアプリ開発を始めてみようとする方々もぜひSwiftに取り組んでみてください。