Swiftのdelegateについて
はじめに
TableViewCell
内にボタンを配置した際の、delegate
についての備忘録になります。
動作環境
【Xcode】Version 12.3
【Swift】Version 5.3.2
実装後の画面
上のセルから順番にボタンをタップした際の出力結果
0番目のボタンがタップされました!
1番目のボタンがタップされました!
2番目のボタンがタップされました!
3番目のボタンがタップされました!
4番目のボタンがタップされました!
実装コード
TableViewCell.swift
import UIKit
// (1)
protocol TableViewCellDelegate {
func buttonTapAction()
}
class TableViewCell: UITableViewCell {
@IBOutlet weak var label: UILabel!
@IBOutlet weak var button: UIButton!
var delegate: TableViewCellDelegate? // (2)
var cellDone: (()->Void)?
override func awakeFromNib() {
super.awakeFromNib()
button.layer.masksToBounds = true
button.layer.cornerRadius = 5
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
@IBAction func buttonTapAction(_ sender: Any) {
cellDone?()
delegate?.buttonTapAction() // (3)
}
}
ViewController.swift
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var tableView: UITableView!
private let CELL_IDENTIFIER = "Cell"
var selectedCellIndex: IndexPath?
override func viewDidLoad() {
super.viewDidLoad()
}
}
extension ViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 5
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: CELL_IDENTIFIER, for: indexPath) as? TableViewCell else {
return UITableViewCell()
}
cell.delegate = self // (4)
cell.cellDone = { [weak self] in
self?.selectedCellIndex = indexPath
}
cell.label.text = "セル:\(indexPath.row)"
return cell
}
}
// (4)
extension ViewController: TableViewCellDelegate {
func buttonTapAction() {
if let selectedCell = selectedCellIndex {
print("\(selectedCell.row)番目のボタンがタップされました!")
}
}
}
実装詳細
1. protocolで宣言
-
protocol
を宣言します。
protocol TableViewCellDelegate {
func buttonTapAction()
}
protocol
とは
import UIKit
// (1)
protocol TableViewCellDelegate {
func buttonTapAction()
}
class TableViewCell: UITableViewCell {
@IBOutlet weak var label: UILabel!
@IBOutlet weak var button: UIButton!
var delegate: TableViewCellDelegate? // (2)
var cellDone: (()->Void)?
override func awakeFromNib() {
super.awakeFromNib()
button.layer.masksToBounds = true
button.layer.cornerRadius = 5
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
@IBAction func buttonTapAction(_ sender: Any) {
cellDone?()
delegate?.buttonTapAction() // (3)
}
}
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var tableView: UITableView!
private let CELL_IDENTIFIER = "Cell"
var selectedCellIndex: IndexPath?
override func viewDidLoad() {
super.viewDidLoad()
}
}
extension ViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 5
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: CELL_IDENTIFIER, for: indexPath) as? TableViewCell else {
return UITableViewCell()
}
cell.delegate = self // (4)
cell.cellDone = { [weak self] in
self?.selectedCellIndex = indexPath
}
cell.label.text = "セル:\(indexPath.row)"
return cell
}
}
// (4)
extension ViewController: TableViewCellDelegate {
func buttonTapAction() {
if let selectedCell = selectedCellIndex {
print("\(selectedCell.row)番目のボタンがタップされました!")
}
}
}
1. protocolで宣言
-
protocol
を宣言します。
protocol TableViewCellDelegate {
func buttonTapAction()
}
protocol
とは
具体的な処理内容は書かず、クラスや構造体が実装するプロパティとメソッドを定義する機能です。
プロトコルを適用したクラスや構造体は、プロトコルに定義されているプロパティとメソッドを必ず実装しなければなりません。
2. delegateを宣言
-
TableViewCell
クラス内にdelegate
を宣言します。
var delegate: TableViewCellDelegate?
delegate
とは
デザインパターンのひとつです。
delegate
は英語で「人に任せる」という意味を持っており、「あるクラスから他のクラスに処理を任せる」というデザインパターンです。
実際の処理はプロトコルを適合する側で実装するため後から変更することができますが、処理を実行する側はどんな処理をするのか意識することなく、呼び出すことができます。
3. 受け渡し元のView
でdelegate
をセット
- 受け渡し元(
@IBAction func buttonTapAction(_ sender: Any)
)にセットします。
delegate?.buttonTapAction()
4. 受け渡し先のView
にdelegate
を呼び出す
- 受け渡し先(
cell
)に呼び出します。
cell.delegate = self
上記を追加すると、下記エラーが出ます。
Cannot assign value of type 'ViewController' to type 'TableViewCellDelegate?'
タイプ「ViewController」の値をタイプ「TableViewCellDelegate?」に割り当てることができません。
これは、上記で説明した通り、プロトコルに定義されているプロパティとメソッドを必ず実装しなければならないためになります。
下記を追加し完成です。
extension ViewController: TableViewCellDelegate {
func buttonTapAction() {
// ここに処理内容がはいります。
}
}
参考
Author And Source
この問題について(Swiftのdelegateについて), 我々は、より多くの情報をここで見つけました https://qiita.com/ayukin/items/fdb7aa9faf71e7222ec0著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .