Swift Delegate カスタムセル 実装処理
delegateについて記事を探したが、一般論でしかなく理解し難いのでまとめておく
やりたいこと
TableView Cellの中のbutton で画面遷移したい。delegate利用
理由:通常ならデリゲートメソッドを利用する。
しかし、xibファイルの中に自分が実装したボタンがあり、ボタン押下時に画面遷移したい。
そのときに選択したセルのオブジェクトも持っていきたい。
通常ならセル選択時に呼ばれるメソッドを利用。これ
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath){
しかし,xibファイルはこれ
xibファイルのボタン押下を取得するために,delegateを自作。
まずプロトコル 今回は、セルのindexPath を次画面で利用したいため、引数に渡してあげる。
protocol UseSegueDelegate { //この関数は、delegateを任された側のクラスで、実装しないといけない。 func moveView(_ index: IndexPath) }
ちなみに、プロトコル名は○○delegateのほうがわかりやすい。
処理を任せる側 xibファイルのクラス
//DayListCellクラス //引数用のプロパティ var index:IndexPath? //これが無いと、delegateメソッドが利用できない。 var delegate:UseSegueDelegate? @IBOutlet weak var count: UILabel! @IBOutlet weak var dayLabel: UILabel! @IBAction func btn_NextPage(_ sender: Any) { delegate?.moveView(index!) }
実装するクラス tableviewのあるクラス
//delegate var index:IndexPath? // PlanListControllerからの画面遷移時にデータを持ってくる var plan: Plans? //日付表示用 var planDays: [Days]? func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { // セルを取得する 先程のxib ファイルにキャストする let cell: DayListCell = tableView.dequeueReusableCell(withIdentifier: "DayCell", for: indexPath) as! DayListCell //日付表示用 let formatter = DateFormatter() formatter.locale = Locale(identifier: "ja_JP") formatter.dateStyle = .medium // セルに表示する値を設定する let date = planDays![indexPath.row].day cell.count.text = "\(String(planDays![indexPath.row].day + 1)) 日目" let dateComponents = DateComponents(day: Int(date)) //datecomponents でday を指定しているのでその分増えていく 1-足す時間 2-開始時間 let showDay = Calendar.current.date(byAdding: dateComponents, to: plan!.start_date!) cell.dayLabel.text = formatter.string(from: showDay!) //xibファイルのdelegateには、このコントロラーを渡す cell.delegate = self //ポイント ここでdelegateのプロパティにTableViewのindexPathを詰め込んでいる cell.index = indexPath return cell }
上記のポイントの箇所により
- プロトコルのプロパティ indexにこのTableViewのindexPathが詰め込まれる
- プロトコルのメソッド func moveView(_ index: IndexPath)が呼ばれる
これはセルのなかのボタン押下時に呼ばれる。indexpathが詰め込まれている
- その後同じクラスに実装しているmoveViewが呼ばれる
func moveView(_ index: IndexPath) { //self.index= このクラスのプロパティ self.index = index //segueを呼ぶ performSegue(withIdentifier: "toFoodList", sender: nil) } //上記performSegueにより呼び出される override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if (segue.identifier == "toFoodList") { let subView = (segue.destination as? FoodListControllerTableViewController)! // modify subView.day_int = self.plan?.days //ここでindexが利用できる。 このプロトコルを実装していないと、[index!.row]を記載するとエラーになる。 //プロトコルを実装したために、エラーにならない。 subView.day = self.planDays![index!.row] } }