Swift의 delegate 정보

11671 단어 XcodeiOSSwifttableView

소개


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이란?



    구체적인 처리 내용은 쓰지 않고, 클래스나 구조체가 구현하는 프로퍼티과 메소드를 정의하는 기능입니다.
    프로토콜을 적용한 클래스나 구조체는, 프로토콜에 정의되고 있는 프로퍼티과 메소드를 반드시 구현하지 않으면 안됩니다.

    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() {
            // ここに処理内容がはいります。
        }
    }
    

    참고


  • 【Swift 입문】난해한 델리게이트(delegate)의 사용법을 이해하자!
  • 【Swift 입문】 프로토콜(protocol)을 사용해 보자!
  • 좋은 웹페이지 즐겨찾기