Delegate 패턴은 iOS 개발에서 매우 자주 사용되는 디자인 패턴 중 하나로,
UIKit에서도 주요한 역할을 한다고 한다.
UITableViewDelegate와 UICollectionViewDelegate는 Delegate 패턴의 대표적인 사례인데,
사용자와 인터페이스 간 상호작용을 처리하는 데 활용된다고 한다.
Delegate는 일종의 대리인으로, 특정 객체의 행동을 다른 객체에 위임하는 디자인 패턴이다.
테이블 뷰의 동작을 제어하기 위해 UITableViewDelegate
프로토콜이 존재한다.
UITableViewDelegate
메서드를 구현하면 테이블 뷰의 동작 (예: 셀 선택, 셀 높이 설정 등)을 "대리"로 처리한다.쉽게 말해, 테이블 뷰는 "무언가 이벤트가 발생하면 Delegate에게 알려주겠다"는 철학으로 설계된 것이다.
didSelectRowAt indexPath
메서드 호출.import UIKit
// Model: 테이블에 표시할 데이터
struct Movie {
let title: String
var year: Int
}
// ViewController: UITableViewController를 상속받아 Controller 역할을 수행
class MovieTableViewController: UITableViewController {
var movies: [Movie] = [
Movie(title: "킹콩", year: 2010),
Movie(title: "해리포터", year: 2008),
Movie(title: "마션", year: 2017),
Movie(title: "부부의 세계", year: 2021),
Movie(title: "킹콩", year: 2010),
]
override func viewDidLoad() {
super.viewDidLoad()
// 테이블 뷰의 레이아웃, 스타일 설정
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "MovieCell")
}
// 테이블 뷰의 셀을 설정하는 메서드
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return movies.count
}
// 각 셀의 내용을 설정하는 메서드
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "MovieCell", for: indexPath)
let movie = movies[indexPath.row]
cell.textLabel?.text = "\(movie.title)의 개봉연도는 \(movie.year) 입니다"
return cell
}
}
이 코드가 UITableViewDelegate와 관련 있는 이유를 말하자면,
이 코드는 UITableViewController를 상속받고 있다.
UITableViewController는 기본적으로 UITableViewDelegate와
UITableViewDataSource를 자동으로 채택하고 구현하는 구조를 제공하는데,
그러니 이미 UITableViewDelegate를 활용해 테이블 뷰의 동작을 정의할 준비가 되어 있다는 뜻.
이 코드에서 테이블 뷰의 동작(셀의 내용, 셀의 개수 등)은
tableView(_:numberOfRowsInSection:)과 tableView(_:cellForRowAt:)
메서드를 통해 정의되었다.
이 메서드들은 UITableViewDataSource 프로토콜의 일부지만,
테이블 뷰와 데이터를 주고받는 역할을 담당하는 점에서 Delegate와 밀접한 관계가 있다.
현재 코드에는 UITableViewDelegate의 메서드가 구현되어 있지 않다.
이벤트를 처리하기위해 Delegate 메서드를 구현해야 해보자면
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let selectedMovie = movies[indexPath.row]
print("\(selectedMovie.title)을 선택했습니다!")
}
현재 코드의 경우
Delegate가 할 수 있는 일이라면
Delegate는 "테이블 뷰의 일부 동작을 컨트롤러(ViewController)에게 위임"한다.
그러니까 테이블 뷰는 셀이 선택되었을 때 무슨 동작을 해야 할지 모른다는 것이다.
그래서 "셀 선택 이벤트를 위임받은 Delegate(뷰 컨트롤러)"가 처리를 하는 것.
이렇게 테이블 뷰와 Delegate는 협력하여 동작을 완성할 수 있다.
indexPath
전달.heightForRowAt
메서드 호출.viewForHeaderInSection
메서드 호출.테이블 뷰의 Delegate는 테이블 뷰와 상호작용하며 정보를 전달받아
개발자가 원하는 동작을 구현할 수 있도록 돕는 역할을 한다는 걸 알 수 있다.
이어서 UICollectionViewDelegate에 대해 알아보자.
UICollectionViewDelegate는 UICollectionView에서 발생하는 사용자 상호작용(이벤트)과 관련된 동작을 처리하기 위해 사용하는 프로토콜이다.
이 프로토콜을 구현하면 셀의 선택, 강조, 특정 동작에 대한 응답을 설정할 수 있고,
사용자의 인터랙션에 따라 동작을 커스터마이징할 수 있기 때문에 UICollectionView를 더 동적으로 사용할 수 있다고 한다.
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath)
func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath)
func collectionView(_ collectionView: UICollectionView, shouldHighlightItemAt indexPath: IndexPath) -> Bool
func collectionView(_ collectionView: UICollectionView, didHighlightItemAt indexPath: IndexPath)
func collectionView(_ collectionView: UICollectionView, didUnhighlightItemAt indexPath: IndexPath)
func collectionView(_ collectionView: UICollectionView, canFocusItemAt indexPath: IndexPath) -> Bool
func collectionView(_ collectionView: UICollectionView, shouldUpdateFocusIn context: UICollectionViewFocusUpdateContext) -> Bool
func collectionView(_ collectionView: UICollectionView, contextMenuConfigurationForItemAt indexPath: IndexPath, point: CGPoint) -> UIContextMenuConfiguration?
Delegate 설정: UICollectionViewDelegate
를 채택한 객체를 delegate
속성에 연결해야 한다. 보통 ViewController가 이를 채택한다.
class MyViewController: UIViewController, UICollectionViewDelegate {
override func viewDidLoad() {
super.viewDidLoad()
collectionView.delegate = self
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print("Item selected at \(indexPath)")
}
}
필요한 메서드 구현: 사용하고자 하는 동작에 맞게 메서드를 구현하면 된다.
UICollectionViewDelegate는 셀의 상호작용을 처리할 수 있는 도구라는 걸 알고있으면 되고,
선택이나 강조와 같은 이벤트를 필요에 따라 구현을 하면 될 것 같다.
오늘 공부를 통해 Delegate가 되게 중요한 기능이구나 라는걸 깨달았다.
테이블 뷰와 컬렉션 뷰가 단순히 데이터를 보여주는 것을 넘어
사용자와 상호작용하는 인터페이스로 동작할 수 있도록 만드는 핵심이
바로 Delegate라는 사실도 알게 되었고,
UITableViewDelegate와 UICollectionViewDelegate를 통해
iOS 개발자는 사용자 경험을 세밀하게 제어할 수 있다는 점에서 UIKit이 유연한 존재임을 알게 되었다.
Delegate 패턴이 처음에는 단순히 "메서드를 구현하는 규약"처럼 보였는데,
사실 실질적으로 어떻게 다른 객체와 연결되고 데이터를 전달하는지 이해하는 데 시간이 많이 걸렸다.
지금도 이걸 다 쓰고 한번 더 읽어보려한다.
오 문자 썸네일 신기해요
다음엔 NotificationCenter해주세요 작가님
이집 공부 잘 되네