Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
Do-hyun-Kim opened this issue Aug 29, 2023 · 4 comments
Labels
Swift Swift CS 개념 공부

Comments

@Do-hyun-Kim
Copy link
Contributor

No description provided.

@Do-hyun-Kim Do-hyun-Kim added the Swift Swift CS 개념 공부 label Aug 29, 2023
@Do-hyun-Kim Do-hyun-Kim changed the title delegate 패턴을 활용하는 경우를 예를 들어 설명하시오. Delegate 패턴을 활용하는 경우를 예를 들어 설명하시오. Aug 29, 2023
@Do-hyun-Kim
Copy link
Contributor Author

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

  • Delegate Pattern 이란 "객체가 자신의 책임을 다른 객체에게 위임(delegate)하는 디자인 패턴" 이라고 한다.
  • 대표적으로 UITableViewDelegate, UICollectionViewDelegate 가 있습니다. 이 같은 경우 책임을 ViewController 에게 위임하여 기능을 대신 수행하도록 한다.
  • Delegate Pattern 이 다른 클래스에도 활용이 될 경우에 상속 을 활용 하는 것보다 적절 합니다.
weak var delegate: UITableViewDelegate? { get set }

Delegate Pattern 장점

  • Protocol 을 사용하여 코드의 재사용성을 확보할 수 있으며, 유지보수 또한 쉽다.
  • delegate Pattern 같은 경우 상속을 하지 않기 때문에 캡슐화를 파괴하지 않아도 되며 유연성을 부여 할 수 있다.

Delegate Pattern 단점

  • 구현하는데에 있어 많은 코드량이 포함되어야 한다.
  • delegate설정에 있어 nil 값이 들어가지 않아야 한다. nil 값이 포함된다면 크래시 오류가 발생한다.
  • delegate Property를 정의할 때 weak 키워드를 선언하지 않을 경우 Strong Reference Cycle 이 발생할 수 있다.

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
Copy link

Delegate Pattern

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

Delegate 패턴의 활용 예

  • UITableView classUITableViewDelegateUITableViewDataSource 프로토콜을 사용하여 테이블 뷰 상호작용, 셀 표시 및 테이블 뷰 레이아웃 변경을 관리한다.
  • CLLocationManagerCLLocationManagerDelegate 를 사용하여 위치 관련 데이터를 앱에 보고한다. 예를들어 iPhone의 GPS 좌표가 있다.
  • UITextViewUITextViewDeleagte를 사용하여 텍스트 뷰의 변경 사항을 보고한다. 새로운 문자 삽입, 선택 변경 및 텍스트 편집이 중단될 때와 같은 경우이다.
    • 뷰 컨트롤러에 델리게이트 함수를 정의하고 텍스트필드에서 동작이 일어나면 델리게이트 함수를 호출하고, 뷰 컨트롤러가 대신 처리해준다

Delegate 패턴을 사용하는 이유

  • 한 클래스에서 다른 클래스로 작업을 경량화하여 전달할 수 있다.
    • 프로토콜만으로 클래스 간 요구 사항을 전달할 수 있어 클래스 간 결합도가 크게 줄어든다
  • subclassing 보다 가볍다.
    • 완전한 클래스나 구조체를 상속받을 필요가 없기 때문이다

📝참고

@ronick-grammer
Copy link
Contributor

ronick-grammer commented Aug 31, 2023

Delegate 패턴이란

  • 객채의 이벤트 제어권에 대한 책임을 위임받아 대신 처리해주는 디자인 패턴
  • 대표적으로 iOS 에서 제공하는 UITableViewDelegate, UITableViewDataSource, UICollectionViewDelegate .. 등이 있으며 iOS에서 발생하는 UI 이벤트에 대한 처리를 delegate 프로토콜을 채택하는 UIViewController 에서 대신 처리해주도록 한다.

이벤트 제어권에 대한 책임을 정의하는 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
Copy link
Member

Delegate 패턴

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

  • 프로토콜 (Protocol) : 대리자가 수신자에게 전달할 내용의 약속(규칙)
  • 수신자 (Receiver) : 대리자가 특정 기능을 수행 후 전달받을 대상
  • 대리자 (Delegate) : 수신자를 대신하여 처리할 대리자

Delegate 패턴 만들기

*UITextFieldDelegate 사용

  1. 프로토콜 채택
class ViewController: UIViewController, UITextFieldDelegate {
    
    let textField = UITextField()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // delegate를 대리자로 설정해주기
        self.textField.delegate = self
    }
}
  1. 메서드 구현
// 텍스트필드가 뷰컨에게 "작업이 끝났어 END 입력해" 라고 전달
func textFieldDidEndEditing(_ textField: UITextField) {
    textField.text = "END"
}
// 텍스트필드가 뷰컨에게 "리턴버튼 누르면 키보드 내려도 돼" 라고 전달
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
    textField.resignFirstResponder()
}

->실제로는 UITextField의 동작이지만 ViewController가 메서드를 전달받아 대신 작업을 한다.

Delegate 패턴 사용 장점

  • 프로토콜 사용으로 뛰어난 재사용성
  • 프로토콜에 필요한 메소드들이 명확하게 명시되며 정보 전달도 가능함

Delegate 패턴 사용 단점

  • 많은 줄의 코드가 필요함
  • Delegate 설정에 nil이 들어가지 않게 주의해야함(크래시를 발생 가능성)
  • 많은 객체에 이벤트를 알려주는것이 어렵고 비효율적임

📝 참조

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Swift Swift CS 개념 공부
Projects
None yet
Development

No branches or pull requests

4 participants