티스토리 뷰
Delegate와 Notification의 차이를 알아보자.
Delegate, Notification
패턴이 나오게 된 배경
종속되어 동작하는 것은 재사용성과 독립적 기능요소 측면에서 바람직하지 않다.
하나의 객체가 다른 객체와 소통은 하지만 묶이진 싫을 때 사용하기 위해 등장했다.
공통점
두 가지 패턴 모두 특정 이벤트가 발생하면 원하는 객체에 알려주어 해당되는 처리를 하는 방법이다.
Delegate
Delegate는 protocol로 지정된 객체가 수행해야 하는 메소드들의 원형을 정해놓은 디자인 패턴이다.
이때 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의 객체(ex: NotificationCenter 같은 외부 객체)가 필요없다.
프로토콜이 컨트롤러의 범위 안에서 정의된다.
단점
많은 줄의 코드가 필요하다.
delegate 설정에 nil이 들어가지 않도록 주의해야 한다.
많은 객체들에게 이벤트를 알려주는 것이 가능은 하지만 어렵고 비효율적이다.
Notification
데이터를 주고 받는 것을 NotificationCenter 라는 싱글턴 객체를 통해 이벤트들의 발생 여부를 옵저버들에게 알려준다. 여기서 옵저버에게 알려주는 것을 post라고 한다. 이때 Notification name이라는 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)
}
}
동작원리
- 한 객체에서 이벤트가 발생했음을 Notification Center에 알린다.
- Notification Center에서 발생된 이벤트를 등록된 모든 Observer에게 알린다.
- 해당 이벤트를 구독하는 Observer가 있다면 해당 화면에서 이벤트에 대한 처리를 할 수 있다.
- 등록된 Observer가 많아지면 모든 Observer 리스트를 찾아가기 때문에 성능이 저하될 수 있다.
장점
많은 줄의 코드를 작성할 필요없이 쉽게 구현이 가능하다.
다수의 객체들에게 동시에 이벤트 발생을 알려줄 수 있다.
Notification과 관련된 정보를 Any? 타입의 object와 [Hashable: Any]? 타입의 userInfo로 전달할 수 있다.
단점
key값으로 Notification 이름과 userInfo를 서로 맞추기 때문에 컴파일 시 구독이 잘 되고 있는지, 올바르게 userInfo의 value를 받아오는지 체크가 불가능하다.
추적이 쉽지 않을 수 있다.
Notification post 이후 정보를 받을 수 없다.
Delegate, Notification 차이점
공통점은 처음에 설명한대로 특정 이벤트가 발생하면 원하는 객체에 알려주어 처리를 한다는 점이다.
Delegate는 protocol을 제작할 때 미리 메소드의 틀을 잡아 놓아야 하며, SomeDelegate라는 변수를 이벤트를 처리할 객체가 들고 있어야 한다.
그에비해 Notification은 위의 과정이 필요없고, 특정 이벤트가 발생하고 Notification Center가 알려주면 그에 맞는 처리를 해주면 된다.
장점으로도 보이는 Notification의 특징은 단점이 될 수도 있다. Delegate를 사용하여 설계하지 않고 Notification으로만 설계를 한다면 다른 사람이 혹은 미래의 내가 유지보수할 때 이 Notification을 누가 구독하고 있는지 추적하기가 어렵다. Delegate로 설계를 했다면 Delegate의 이름, protocol의 메소드 등을 통해 로직의 흐름을 따라가기 쉽다.
Delegate, Notification 언제 사용할까?
하나의 이벤트에 다수의 구독자가 있다면 Notification, 그 외에는 로직을 파악하기 쉬운 Delegate를 사용하는게 좋을 것 같다.
하나의 이벤트에 많은 구독자를 Delegate로 구현하기에는 Delegate를 다 들고있어야 하고 코드양이 많아지게 되기 때문에 비효율적이라고 생각한다. 그렇다고 모든 것을 Notification을 사용한다면 차이점에서 설명한대로 로직을 파악하기 어렵기 때문이다.
'iOS > Swift' 카테고리의 다른 글
[Swift] 열거형 (Enumerations) (1) | 2022.12.07 |
---|---|
[Swift] Strong, Weak, Unowned 참조 (0) | 2022.12.05 |
[Swift] Generic (2) (0) | 2022.11.21 |
[Swift] Generic (1) (0) | 2022.11.19 |
[Swift] GCD(Grand Central Dispatch) (0) | 2022.11.14 |
- Total
- Today
- Yesterday
- CodingTest
- frame과 bounds 차이
- OCR
- docker
- AWS
- 곰튀김
- Custom
- ChatGPT
- enumerations
- file private
- strcut
- Protocol
- Swift
- MVVM
- delegate
- onTapGesture
- 의미있는이름
- tabview
- kakao
- Xcode
- Generic
- ObservedObject
- IOS
- AWS Fargate
- Login
- Git
- navigation
- 카메라
- rxswift
- SwiftUI
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |