Apple-CS-interview / iOS-CS-interview

7 stars 1 forks source link

Delegate 패턴을 활용하는 경우를 예를 들어 설명하시오. #11

Open Do-hyun-Kim opened 1 year ago

Do-hyun-Kim commented 1 year ago

Delegate 패턴을 활용하는 경우를 예를 들어 설명하시오.

weak var delegate: UITableViewDelegate? { get set }

Delegate Pattern 장점

Delegate Pattern 단점

Delegate Pattern

enum Menu {
    case Macchiato
    case Latte
    case Americano
}

protocol MachineViewDelegate: AnyObject {
    func didSelectedCoffee(menu: Menu) -> Menu
}

class Machine {
    weak var delegate: MachineViewDelegate?

    func makeCoffee(menu: Menu) {
        self.delegate?.didSelectedCoffee(menu: menu)
        print("\(menu) 커피를 만들어 주었습니다.")
    }

}

class Barista: MachineViewDelegate {

    init(coffeeMachine: Machine) {
        coffeeMachine.delegate = self
    }

    func didSelectedCoffee(menu: Menu) -> Menu {
        print("바리스타는 커피 머신의 \(menu)를 선택하였습니다.")
        return menu
    }

}

let jennyMachine: Machine = Machine()
let jennyBarista: Barista = Barista(coffeeMachine: jennyMachine)
jennyMachine.makeCoffee(menu: .Americano)

📝 참고 사이트

vichye-1 commented 1 year ago

Delegate Pattern

프로토콜을 이용해서 클래스나 구조체가 자신의 권한을 다른 타입의 인스턴스에게 위임하여 일을 처리하는 방식의 디자인 패턴 (어떤 객체가 해야할 일을 대신해서 처리해주는 것)

Delegate 패턴의 활용 예

Delegate 패턴을 사용하는 이유

📝참고

ronick-grammer commented 1 year ago

Delegate 패턴이란

이벤트 제어권에 대한 책임을 정의하는 delegate 프로토콜을 정의한다

protocol DelegateProtocol {
    func tappedButton(value: String)
    ...
}

위임해주는 객채는 delegate라는 위임자 프로퍼티를 가진다

class Delegator {
    var delegate: DelegateProtocol?

    lazy var button: UIButton = {
        let button = UIButton()
        button.addTarget(self, action: #selector(tappedButton), for: .touchUpInside)
        return button
    }()

    init() {}

    @objc func tappedButton() {
        delegate?.tappedButton(value: "Tapped Button")
    }
}

위임받는 객체는 이 delegate 프로토콜을 채택하고 내부에 정의된 메서드를 구현한다

class Delegatee: DelegateProtocol {

    var delegator = Delegator()

    init() {
        delegator.delegate = self
    }

    func tappedButton(value: String) {
        print("value: ", value)
    }
}

위임해주는 객체의 위임자 프로퍼티인 delegate는 weak 키워드로 선언하는 것이 좋다

위임받는 객체(delegatee)에서 위임해주는 객체(delegator)의 delegate에 위임받는 객체를 참조하게 하는 순간(delegator.delegate = self) '강한(strong)참조가 발생하여 '순환참조(retain cycle)' 가 발생할 위험이 있다.

이 때문에 delegate 프로토콜 타입을 weak 키워드를 선언함으로서 참조 카운트(reference count)를 증가시키지 않도록하여 순환참조를 방지하도록 할 필요가 있다. 이때 protocol 은 값타입도 참조타입도 아닌 추상타입이기 때문에 delegate 프로토콜이 AnyObject 프로토콜을 채택하게 하여 컴파일러에게 참조타입임을 알려야 한다. 이렇게 해야만 weak 키워드를 사용하여 참조 카운트를 관리할 수 있다.

protocol DelegateProtocol: AnyObject {
    func tappedButton(value: String)
    ...
}

class Delegator {
    weak var delegate: DelegateProtocol?
    ...

Delegate 패턴을 사용하는 이유

iOS 에서 delegate 패턴은 어떤 뷰의 이벤트에 대한 처리를 다른 뷰에서 해줄때 사용할 수 있는 유용한 패턴이다. delegate 패턴을 사용하지 않게 될 경우, 전역변수를 사용한다거나 UserDefaults 등을 사용하여 무분별하게 로컬에 데이터를 저장하고 사용함으로서 불편성과 위험성을 증가시키는 코드를 작성하게 될 수 있다.

📝 참고 사이트

Hminchae commented 1 year ago

Delegate 패턴

어떠한 객체가 해야할 일을 다른 객체에게 위임하는 것

Delegate 패턴 사용 장점

Delegate 패턴 사용 단점

📝 참조