Swift의 Protocol을 이용한 Delegate 패턴
strong reference cycle 피하기
UITableView를 사용하면 반드시 dataSource와 delegate를 설정하게 됩니다.
이 속성들은 weak reference입니다.
ViewController는 TableView에 대한 reference를 갖고, 보통 ViewController에 delegate나 dataSource를 구현해서 TableView는 ViewController에 대한 reference를 가집니다.
ViewController -> TableView
TableView -> ViewController
이것을 합치면 reference cycle이 만들어집니다.

둘 다 서로에 대한 strong reference를 가지게 되면 메모리 해제가 안됩니다.
그래서, UITableView는 delegate와 dataSource 속성이 weak reference입니다.
Swift에서 깜빡하기 좋네
Swift로 오면서 delegate 패턴을 구현하기 위해서 protocol을 사용하는데 이때 strong reference cycle에 빠지기 쉽습니다.
다음은 ViewController에 UITableView를 위치시키고, Cell에서 필요한 protocol을 ViewController에 구현한 예제입니다.
Protocol
protocol GreetProtocol {
func greet() -> Void
}ViewController
class MasterViewController: UITableViewController {
...생략...
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! GCell
cell.delegate = self
let object = objects[indexPath.row] as! NSDate
cell.textLabel!.text = object.description
return cell
}
...생략...
}
extension MasterViewController: GreetProtocol {
func greet() {
print("Hello, cell")
}
}TableViewCell
class GCell: UITableViewCell {
var delegate: GreetProtocol?
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
deinit {
if let delegate = delegate {
delegate.greet()
}
}
...생략...
}위의 코드는 strong reference cycle을 구성합니다.
ViewController의 deinit가 호출되지 않습니다. 즉, 메모리 누수가 발생합니다.

해결책
이를 해결하기 위해서는 protocol 정의를 수정하고 protocol에 대한 참조를 weak로 해주어야 합니다.
Protocol
protocol GreetProtocol: class {
func greet() -> Void
}protocol이 class로 구현되어야 weak reference가 가능합니다.
아래 코드는 delegate 정의에 weak를 추가하였습니다.
TableViewCell
class GCell: UITableViewCell {
weak var delegate: GreetProtocol?
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
deinit {
if let delegate = delegate {
delegate.greet()
}
}
...생략...
}