본문 바로가기
iOS Swift/Study

Swift Delegate 패턴 예제로 알아보기

by 야고이 2024. 4. 30.
728x90

240430

Delegate 패턴은 객체 간의 통신과 이벤트 처리를 위한 디자인 패턴 중 하나입니다. 주로 객체 간의 느슨한 결합(Loose coupling)을 유지하면서 하나의 객체가 다른 객체의 동작을 대신 처리할 수 있도록 합니다.

솔직히 느슨한 결합이 뭔말인지 모르겠다

더보기

느슨한 결합(Loose coupling)은 객체 간의 의존성을 최소화하여 각각의 객체가 독립적으로 존재할 수 있도록 하는 소프트웨어 디자인 원칙입니다. 이것은 소프트웨어를 더 견고하고 유연하게 만들어줍니다.

느슨한 결합을 유지하는 것은 객체 간의 상호작용을 최소한으로 제한하고, 각 객체가 다른 객체에 대해 가능한 적은 정보를 알도록 하는 것을 의미합니다. 이를 통해 다음과 같은 장점이 있습니다:

  1. 유연성(Flexibility): 객체가 다른 객체에 의존하지 않거나 가능한 적은 의존성을 가지고 있을 때, 코드를 변경하거나 확장할 때 다른 객체에 영향을 미치지 않고 해당 객체를 수정할 수 있습니다. 즉, 변경이 쉬워집니다.
  2. 재사용성(Reusability): 각각의 객체가 독립적으로 존재할 수 있으므로, 이러한 객체들을 다른 곳에서 재사용할 수 있습니다.
  3. 유닛 테스트(Unit Testing): 느슨한 결합은 테스트하기 쉬운 코드를 작성하는 데 도움이 됩니다. 의존성이 적은 객체는 단위 테스트를 수행하기 용이하며, 테스트를 더욱 견고하게 만듭니다.

Delegate 패턴은 이러한 느슨한 결합을 실현하는데 도움이 됩니다. 대리자 객체를 통해 객체 간의 통신이 이루어지므로, 각 객체는 상대 객체에 직접적으로 의존하지 않고, 대신 인터페이스를 통해 상호작용합니다. 이는 코드를 유연하고 재사용 가능하게 만들어줍니다.

모르겠어서 다른 블로그에 있는 예제 가져와서 직접 구현해봤다

참고한 블로그

 

장바구니에 상품을 담으면 갯수 선택 창이 뜨고, 갯수를 선택하고 최종으로 장바구니에 담으면 확인 얼럿창이 뜨는 예제 입니다

-정리-

  1. 첫화면에 장바구니 버튼을 클릭 
  2. 두번째 화면에서 갯수 선택
  3. 다시 첫번째 화면으로 돌아오면서 추가된 갯수 확인용 얼럿창 뜸

첫번째 화면 - 두번째 화면 - 다시 첫번째 화면으로 돌아와 뜨는 얼럿창

프로토콜을 하나 만들어 줍니다

import Foundation

protocol CartDelegate {
    func alarmCartIsFilled(itemCount: Int)
}

프로토콜이 먼지 모르겠다,, 라고 하시면 구글 선생님이 알려주실검미다

 

두번째 화면에 만든 프로토콜을 생성해 줍니다

import UIKit
import SnapKit

class CartViewController: UIViewController {

    var itemCount: Int = 0
    var delegate: CartDelegate? // 프로토콜 생성
    
    let view1 = UIView()
    let priceLabel = UILabel()
    let itemCountLabel = UILabel()
    let stepper = UIStepper()
    let buyButton = UIButton()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
 	// UI 부분 생략
    }
    
    @objc func stepperValueChanged(_ sender: UIStepper) {
        print("itemCount\(itemCount)")
//        print("itemCountLabel\(itemCountLabel)")
        itemCount = Int(sender.value)
        itemCountLabel.text = Int(sender.value).description
    }
    
    @objc func insertCartButtonTapped(_ sender: UIButton) {
        dismiss(animated: true, completion: nil) // 이전화면으로 돌아가기
        delegate?.alarmCartIsFilled(itemCount: itemCount) // 얼럿실행
    }
}

여기서부터 너무 헷갈렸는데 

두번째 화면에서 "장바구니 담기" 버튼을 누르면 첫번째 화면으로 돌아가면 얼럿창이 떠야하므로

버튼에다가 이전화면으로 돌아가는 코드와, 장바구니에 담긴 갯수를 알려줄 메소드를 작성합니다

 

메소드에 대한 구현은 어디서 하지? 싶은데 이제 할겁니다

 

대리자 위임하기

두번째 화면에서 "장바구니 담기" 버튼을 눌렀을 때 첫번째 화면으로 돌아가면서 얼럿창이 보이게 하고 싶다고 했죠?

그러면 얼럿창을 띄우는건 두번째 화면에서 시키는건데 우리가 얼럿창을 띄우고 싶은 곳은 첫번째 화면입니다!

 

근데 두번째 화면에서 첫번째에 어떻게 띄우죠,,,,

그래서...! 여기서 대리자를 위임하는 행위를 하는 것 인데요

// 두번째 화면으로 이동하는 함수
@objc func moveToCart() {
    print("장바구니 눌림")
    let cartVC = CartViewController()
    navigationController?.pushViewController(cartVC, animated: true)
    cartVC.delegate = self
    self.present(cartVC, animated: true, completion: nil)
}

 

cartVC.delegate = self

이 코드가 위임을 해주는 행위 입니다

CartViewController()의 delegate 를  self 즉, 첫번째 화면인 ViewController 에서 하겠다는 거죠!

import UIKit
import SnapKit

class ViewController: UIViewController, CartDelegate {

    var cartButton = UIButton()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        view.addSubview(cartButton)
        
        cartButton.snp.makeConstraints { make in
            make.centerX.centerY.equalToSuperview()
        }
        cartButton.setImage(UIImage(systemName: "cart"), for: .normal)
        cartButton.addTarget(self, action: #selector(moveToCart), for: .touchUpInside)
        
    }

	// 두번째 화면으로 이동하는 함수
    @objc func moveToCart() {
        print("장바구니 눌림")
        let cartVC = CartViewController()
        navigationController?.pushViewController(cartVC, animated: true)
        cartVC.delegate = self
        self.present(cartVC, animated: true, completion: nil)
    }
    
    
    // 장바구니에 담긴 갯수 얼럿창
    func alarmCartIsFilled(itemCount: Int) {
        let alertVC = UIAlertController(title: "장바구니 확인", message: "장바구니에 \(itemCount)개의 상품이 추가되었습니다.", preferredStyle: .alert)
        let okAction = UIAlertAction(title: "확인", style: .default, handler: nil)
        alertVC.addAction(okAction)
        present(alertVC, animated: true, completion: nil)
    }

}

그리고 첫번째 화면에 만들어둔 프로토콜도 채택해야합니다 그래야 사용할 수 있어요

 

얼럿창을 띄우는건 첫번째 화면에서 이루어지니까 그 내용인 메소드도 여기서 만들어 줍니다!

자주쓰는 테이블뷰나 콜렉션뷰도 델리게이트를 왜 하는지 몰랐는데 이제야 알게되었습니다,,,

개발 공부 두달이나 되어서 깨달은 나,, 그래 이제라도 알았으니 됐어 응,,

728x90

댓글