【Delegate】ViewController間でデータをやり取りする方法

複数の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を使うと便利です。

ABOUTこの記事をかいた人

個人アプリ開発者。Python、Swift、Unityのことを発信します。月間2.5万PVブログ運営。 Twitter:@yamagablog