複数のViewControllerの間でデータをやり取りしたい時があります。
例えば以下のアプリのようにTableViewでタッチされたお店を、地図上のピンで選択する時です。
このように異なるViewの間でデータをやり取りするにはSwiftのdelegateを使うと実装できます。
ピンを選択する機能はMapViewでないとできません。
しかし、Delegateを使うとピンを選択する機能をTableViewに与えることができます。
そうすれば、TableViewで選択された情報をもとにピンを選択することができます。
MapViewのコントローラをMapVC、
TableViewのコントローラをSemiModalVCとして説明していきます。
プロトコル
まずはプロトコルを作成します。
MapVCの中に以下を記載します。
protocol RestMapDelegate { func selectAnnotation(index:Int) }
プロトコルで定める関数はピンを選択する機能です。
プロトコルに批准する
上記のプロトコルをMapVCで批准し、ピンを選択する処理を実装します。
class MapVC: UIViewController, MKMapViewDelegate, FloatingPanelControllerDelegate,RestMapDelegate{ func selectAnnotation(index: Int) { dispMap.selectAnnotation(annotations[index], animated: true) } }
delegate変数を追加する
SemiModalVCの中にdelegate変数を追加します。
class SemiModalVC: UIViewController, UITableViewDelegate, UITableViewDataSource { var delegate:RestMapDelegate? }
ViewController同志をdelegateで結びつける
SemiModalVCとMapVCを結びつけます。
var fpc:FloatingPanelController! func showSemiModal(restList:[Restaurant]){ fpc = FloatingPanelController() fpc.delegate = self fpc.surfaceView.cornerRadius = 24.0 guard let vc = self.storyboard?.instantiateViewController(withIdentifier: "fpc") as? SemiModalVC else { return } vc.restList = restList vc.delegate = self fpc.set(contentViewController: vc) fpc.addPanel(toParent: self) }
SemiModalVCをインスタンス化して、プロパティであるdelegateにMapVC自身を設定します。
テーブルが選択された時にピンを選択する
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { delegate?.selectAnnotation(index: indexPath.row) }
選択されたテーブルの行番号を使ってピン(annotation)を選択する関数を実行しています。
こんな感じでVC間のやり取りはDelegateを使うと便利です。