거의 알고리즘 일기장
delegate 패턴 (with swift) 본문
요즘 ios 개발을 진행중인데, 실제로 적용해본 기술들을 블로그에 적어볼까 한다.
이번에는 ios 개발에서 이벤트 처리를 하면서 자주 사용하게되는 delegate 패턴이다!
🤔 delegate 패턴???
위임자를 갖고 있는 객체가 자신의 일을 다른 객체에게 위임하여 일을 처리하는 패턴. 부분적으로 확장해서 일을 처리한다고도 생각할수있다.
객체 1과 객체 2가 있다고 하자
객체 1이 어떤 함수를 실행했을때, 연속적으로 사람 2도 무언가를 하게 만들고 싶을수 있다.
이걸 구현하기 위해서는 일반적으로 객체 1이 객체 2를 가지고 있는 형태여야 가능하다.
그런데 delegate 패턴을 쓰게 되면 객체 1이 객체 2에 대해서 전혀 모르더라도 일을 시킬수 있다.
⛏실습
위에서 저렇게 설명했어도 뭔 🐶소린가 할 수 있다.
이번에는 내가 직접 겪었던 상황을 단순화시킨 예제로 코드를 짜가면서 설명하겠다.
1. 구현하고 싶은 사항
간략하게 설명하자면 스크립트가 두개가 있다.
- Tableview가 들어가 있는 스크립트
- TableViewCell이 들어가 있는 스크립트
하고 싶은 일은 TableViewCell 안에 있는 button을 클릭했을시에 해당 index의 cellList 안의 item을 삭제하고 싶다.
그러니까 2번 스크립트안에 있는 버튼에서 이벤트가 발생했는데, 1번 스크립트에 있는 데이터를 수정하고 싶은거다. 이럴때 delegate 패턴을 이용할수 있다.
2. 코드
2번 스크립트 ( TableViewCell.swift )
//TableViewCell.swift
import UIKit
protocol TableViewCellDelegate: AnyObject {
func didTapButton(index: Int?)
}
class TableViewCell: UITableViewCell {
static let identifier = "TableViewCell"
let button = UIButton()
var index: Int?
//delegate 변수, 일을 위임할때 필요하다!
weak var delegate: TableViewCellDelegate?
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
setupLayout()
setupControl()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func setupLayout(){
contentView.addSubview(button)
button.backgroundColor = UIColor.systemPink
button.snp.makeConstraints { make in
make.top.left.bottom.right.equalToSuperview().inset(10)
}
}
func setupControl() {
//이벤트 연결
button.addTarget(self, action: #selector(onTapButton), for: .touchUpInside)
}
@objc
func onTapButton() {
//버튼이 눌렸을때 실행되는 부분 이건 1번 스크립트에서 구현내용을 정의해놓을 것이다
self.delegate?.didTapButton(index: index)
}
}
1번 스크립트 ( ViewController.swift )
// ViewController.swift
import UIKit
import SnapKit
class ViewController: UIViewController {
let tableView = UITableView()
var cellList = ["안녕", "봄"]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.view.addSubview(tableView)
tableView.delegate = self
tableView.dataSource = self
tableView.register(TableViewCell.self, forCellReuseIdentifier: TableViewCell.identifier)
tableView.snp.makeConstraints { make in
make.top.left.right.bottom.equalToSuperview()
}
// autoHeight
tableView.rowHeight = UITableView.automaticDimension
tableView.estimatedRowHeight = UITableView.automaticDimension
}
}
extension ViewController: UITableViewDelegate, UITableViewDataSource{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return cellList.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
guard let cell = tableView.dequeueReusableCell(withIdentifier: TableViewCell.identifier, for: indexPath) as? TableViewCell else{
return UITableViewCell()
}
cell.index = indexPath.row
cell.button.setTitle(cellList[indexPath.row], for: .normal)
//이 코드가 중요한데 cell의 일을 내가 대신 처리하겠다는 부분이다.
cell.delegate = self
return cell
}
}
extension ViewController: TableViewCellDelegate {
//didTapButton 구현부분 작성
func didTapButton(index: Int?) {
print("didTapButton")
guard (index != nil) else {
return
}
print("\(cellList[index!]) 삭제")
cellList.remove(at: index!)
tableView.reloadData()
}
}
필요한 부분은 주석에 적어놓았다.
😚 결론
delegate패턴.. 이 주제는 아주 쉽다고 생각했는데, 설명하려니까 말문이 막힌다..
난해하게 설명한거 같은데.. 나중에 고칠기회가 된다면 글 수정을 하겠다. ㅋㅋ
추가적으로 중요한 부분은 언제 이 패턴을 사용하는가? 이게 제일 중요한데
다른 블로그에서 본 글인데 , "Delegate는 어떤 객체가 해야 하는 일을 부분적으로 확장해서 대신 처리를 한다."
이 말이 delegate를 언제 사용할지를 판단할때 도움을 주는 글인거 같다.
📚 참고
https://velog.io/@iwwuf7/Swift-Delegate-Pattern%EC%97%90-%EB%8C%80%ED%95%B4%EC%84%9C
'IOS' 카테고리의 다른 글
snapkit 라이브러리 사용법 (with ios) (0) | 2021.10.02 |
---|---|
LineHeight 에 대한 생각 (with ios) (0) | 2021.09.21 |
pdf image 적용 (with ios) (0) | 2021.09.19 |
Localization (with ios) (0) | 2021.09.19 |
UITableView 쓸때 주의점 (with ios) (0) | 2021.09.12 |