[ iOS ]Delegate, Notification 방식의 차이

이숭인·2021년 8월 5일
0

Mastering iOS

목록 보기
10/11

각각이 어떤 방식으로 사용되는지
언제 사용되는지

Delegate


Delegate 는 보통 Protocol 을 정의하여 사용합니다.


예제코드

// 1) Delegate 프로토콜 선언
protocol SomeDelegate {
    func someFunction(someProperty: Int)
}

class SomeView: UIView {
    // 2) 순환 참조를 막기 위해 weak으로 delegate 프로퍼티를 가지고 있음
    weak var delegate: SomeDelegate?
    
    func someTapped(num: Int) {
        // 3) 이벤트가 일어날 시 delegate가 동작하게끔 함
        delegate?.someFunction(someProperty: num)
    }
}
// 4) Delegate 프로토콜을 따르도록 함
class SomeController: SomeDelegate {
    var view: SomeView?
    
    init() {
        view = SomeView()
        // 6) delegate를 자신으로 설정
        view?.delegate = self
        someFunction(someProperty: 0)
    }
    
    // 5) Delegate 프로토콜에 적힌 메소드 구현
    func someFunction(someProperty: Int) {
        print(someProperty)
    }
}

let someController = SomeController()
// prints 0

장점

  • 엄격한 Syntax 로 인해 프로토콜에 필요한 메소드들이 명확하게 명시되어 있습니다.

  • 프로코콜에 정의되어 있는 메소드 들을 구현하지 않으면 컴파일 시 경고 혹은 에러 가 발생합니다.

  • 커뮤니케이션 과정을 유지하고 모니터링하는 제 3의 객체(NotificationCenter) 가 필요하지 않습니다.

단점

  • 많은 줄의 코드 가 필요합니다.

  • delegate 설정에 nil이 들어가지 않게 주의해야 합니다. (crash 주된 원인)

  • 많은 객체들에게 이벤트를 알리는것이 어렵고 비효율적 입니다.


Notification

NotificationCenter 라는 싱글턴 객체 를 통해서 이벤트들의 발생 여부를 옵저버를 등록한 객체 들에게 Notificationpost 하는 방식으로 사용합니다.

NotificationName 이라는 key 값 을 통해 보내고 받을 수 있습니다.


예제 코드


// 1) Notification을 보내는 ViewController
class PostViewController: UIViewController {
    @IBOutlet var sendNotificationButton: UIButton!
    
    @IBAction func sendNotificationTapped(_ sender: UIButton) {
        guard let backgroundColor = view.backgroundColor else { return }
      
        // Notification에 object와 dictionary 형태의 userInfo를 같이 실어서 보낸다.
        NotificationCenter.default.post(name: Notification.Name("notification"), object: sendNotificationButton, userInfo: ["backgroundColor": backgroundColor])
    }
}

// 2) Notification을 받는 ViewController
class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        // 옵저버를 추가해 구독이 가능하게끔 함
        NotificationCenter.default.addObserver(self, selector: #selector(notificationReceived(notification:)), name: Notification.Name("notification"), object: nil)
    }
    
    // iOS 9 이상이 아닐 경우에는 removeObserver를 해줘야 함
    deinit {
        NotificationCetner.default.removeObserver(self)
    }
    
    @objc func notificationReceived(notification: Notification) {
        // Notification에 담겨진 object와 userInfo를 얻어 처리 가능
        guard let notificationObject = notification.object as? UIButton else { return }
        print(notificationObject.titleLabel?.text ?? "Text is Empty")
        
        guard let notificationUserInfo = notification.userInfo as? [String: UIColor],
            let postViewBackgroundColor = notificationUserInfo["backgroundColor"] else { return }
        print(postViewBackgroundColor)
    }
}

장점

  • 많은 줄의 코드 가 필요없이 쉽게 구현 가능합니다.

  • 다수의 객체 들에 동시에 이벤트를 전달할 수 있습니다.

  • Notoification 과 관련된 정보를 Any? 타입의 object ,
    [AnyHashable: Any]? 타입의 userInfo전달 할 수 있습니다.

단점

  • key 값으로 Notification 의 이름과 userInfo 를 서로 맞추기 때문에 컴파일 시 구독이 잘 되고 있는지 , 올바르게 userInfovalue 를 받아오는지 확인이 불가능합니다.

  • Notificationpost 이후 그에 대한 응답 정보를 받을 수 없습니다.




When to use delegation, notification


Delegation 패턴 은 각각의 객체가 delegate 를 설정하여 이벤트에 대한 처리를 합니다.

먼저, Notification , Delegation 패턴으로 많은 객체들 에 이벤트를 전달해야 하는 경우를 생각해 봅시다.

Notification 의 경우, 특정 키 값 을 가진 notification 이 하나의 이벤트를 post 하게 되면 해당하는 키 값을 가진 notification 을 구독 하고 있는 모두에게 이벤트를 전달 하게 됩니다.

Delegation 의 경우, 이벤트를 전달받아야 하는 각각의 객체들delegate설정 해줘야 합니다.

명확한 답은 없지만, 많은 객체들이벤트를 전달 해야 하는 경우, Notification 을 사용하고 그 외에는 코드의 흐름을 이해하기 쉽고 추적이 쉬운 Delegate 를 사용하는게 좋을 것 같습니다.

profile
iOS Developer

0개의 댓글