Lagacy๋ฅผ Combine ์ „ํ™˜ํ•˜๋ฉด์„œ ๋ฐฐ์› ๋˜ Tip๋“ค์„ ์ ์–ด๋ณธ๋‹ค. Notification Cetner์— ๊ฑธ์—ˆ๋˜ Observer๋ฅผ Publisher๋กœ ์ „ํ™˜ํ•˜๋Š” ๊ฒƒ์— ๋Œ€ํ•œ ๊ธ€์ด๋‹ค.

publisher(for:object:)

iOS 13๋ถ€ํ„ฐ Notification Center์—์„œ ๊ธฐ๋ณธ์ ์œผ๋กœ ์ œ๊ณตํ•œ๋‹ค. addObserver ํ–ˆ๋˜ ๊ฒƒ์„ ์ด property๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋‹ค. ๊ธฐ์กด์—๋Š” VC๋ฅผ ๋„˜์–ด๊ฐ€๋Š” ๊ฒฝ์šฐ์— removeObserver๋ฅผ ํ•ญ์ƒํ•ด์คฌ์–ด์•ผ ํ–ˆ๋Š”๋ฐ, ์ด๋ ‡๊ฒŒ ํ•  ๊ฒฝ์šฐ ์ฝ”๋“œ๊ฐ€ ๋ณด๋‹ค ๊ฐ„๊ฒฐํ•ด์ง€๊ณ  ๋กœ์ง์„ ์ฝ๊ธฐ ์‰ฌ์›Œ์ง„๋‹ค๋Š” ์žฅ์ ์ด ์žˆ๋‹ค.

Publisher ์‚ฌ์šฉํ•˜๊ธฐ

override func viewWillAppear() {
    super.viewWillAppear()
    let notification = Notification.Name("MyNotification")
    self.observer = NotificationCenter.default.addObserver(forName: notification, object: nil, queue: nil) { notification in
        // Some Action
    }
 
    // ๋˜๋Š”
 
    self.observer = NotificationCenter.default.addObserver(self, selecter: #selector(self.reloadData(), name: notification, object: nil))
}
 
override func viewWillDisappear() {
    super.viewWillDisappear()
    NotificationCenter.default.removeObserver(self.observer)
}

๊ธฐ์กด์˜ ๊ฒฝ์šฐ ์œ„์™€ ๊ฐ™์ด ์‚ฌ์šฉํ–ˆ์„ ๊ฒƒ์ด๋‹ค. ์ฆ‰, ์–ด๋”˜๊ฐ€์—์„œ addObserver๋ฅผ ํ•ด์ฃผ๊ณ , removeObserver๋ฅผ ํ•ด์ฃผ์—ˆ์–ด์•ผ ํ–ˆ๋‹ค.

 
func addSubscribers() {
    let notificationName = Notification.Name("MyNotification")
    NotificationCenter.default.publisher(for: notificationName, object: nil).publisher
        .receive(on: DispatchQueue.main)
        .sink { [weak self] notification in
            self.reloadData(notification)
        }
        .store(in: &self.cancellables)
}

์ด๋ ‡๊ฒŒ ์‚ฌ์šฉํ•˜๋ฉด, ํ•ด๋‹น VC๊ฐ€ ํ• ๋‹นํ•ด์ œ๋˜๋Š” ์ˆœ๊ฐ„ self.cancellables๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ํ•ด์ œ๋˜๋ฉด์„œ subscriber๋“ค์ด ๋ชจ๋‘ ์ œ๊ฑฐ๋œ๋‹ค. ๊ทธ๋ž˜์„œ ์ถ”๊ฐ€์ ์œผ๋กœ removeObserver๋ฅผ ํ•ด์ค„ ํ•„์š”๊ฐ€ ์—†๋‹ค.

Notification Combine ์ „ํ™˜ํ•˜๊ธฐ

ํŠน์ • ํ•˜๋‚˜์˜ ๊ฐ์ฒด์—์„œ ๋‹ค์–‘ํ•œ publisher๋ฅผ ๋ณด๋‚ด์ฃผ์–ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ๋‹ค. ๋‹ค์–‘ํ•œ ๊ณณ์—์„œ ์š”์ฒญ์ด ๋“ค์–ด์˜ค๊ธฐ ๋•Œ๋ฌธ์— singleton์œผ๋กœ ์ œ์ž‘ํ•˜๋Š” ํŒ๋‹จ์ด ์˜ณ์•˜์„ ๊ฒฝ์šฐ์ด๋‹ค. ์ด๋Ÿฐ ๊ฒฝ์šฐ, ๊ฐ๊ฐ์˜ ํ™”๋ฉด์—์„œ ์œ„์™€ ๊ฐ™์ด NotificationCenter.default.publisher์™€ ๊ฐ™์ด ๋“ฑ๋กํ•ด์„œ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด ์ค‘๋ณต๋œ ์ฝ”๋“œ๋„ ๋งŽ๊ณ  ๊ฐ€๋…์„ฑ์ด ๋–จ์–ด์งˆ ๊ฒƒ์ด๋‹ค.

์ด๋Ÿฐ ๊ฒฝ์šฐ, singleton ๊ฐ์ฒด์— publisher๋ฅผ ์•„์˜ˆ ๋‹ฌ์•„๋ฒ„๋ ค์„œ, ๋‹ค์–‘ํ•œ ํ™”๋ฉด์—์„œ ์ง์ ‘ ์ ‘๊ทผํ•˜์—ฌ ์‚ฌ์šฉํ•˜๋„๋ก ํ•˜๋Š” ๊ฒƒ์ด ์ข‹๊ฒ ๋‹ค. ํŠน์ • ๋ฐ์ดํ„ฐ๊ฐ€ ์—…๋ฐ์ดํŠธ ๋œ ์‹œ๊ธฐ์—, ๋ณ€๊ฒฝ๋œ ๊ฐ’์„ ์ œ๊ณตํ•˜๋Š” publisher๋ฅผ ๋งŒ๋“ ๋‹ค๊ณ  ์ƒ๊ฐํ•ด๋ณด์ž.

final class DataManager {
    static let shared = DataManager()
 
    static let notificationName = Notification.Name(rawValue: "DataChange")
 
    private func someUpdateFunction() {
        // Do some jobs
        NotificationCenter.default.post(name: Self.notificationName, object: self, userInfo: ["update": update])
    }
}
 
final class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        self.observer = NotificationCenter.default.addObserver(forName: DataManager.shared.notifiactionName)
    }
 
    override func viewDidDisappear() {
        super.viewDidDisappear()
        NotificationCenter.default.removeObserver(self.observer)
    }
}

๊ธฐ์กด ๊ฐ™์€ ๊ฒฝ์šฐ์—๋Š”, ์ด๋Ÿฐ์‹์œผ๋กœ ํŠน์ • ๊ฐ์ฒด์—์„œ ๋ณด๋‚ธ ๋ฉ”์‹œ์ง€๋ฅผ Observer๋ฅผ ๋“ฑ๋กํ•˜์—ฌ ๋ฐ›์€ ๋’ค ์ฒ˜๋ฆฌํ–ˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ด๋ณด์ž. ์ฝ”๋“œ๋Š” ๋Œ€๊ฐ• ์ง  ๊ฒƒ์ด๋‹ค.

internal protocol DataManageable: AnyObject {
    var updatedPublisher: AnyPublisher<Update, Never> { get }
}
 
final class DataManager: DataManageable {
    static let shared = DataManager()
 
    private updatedSubject = PassthroughSubject<Update, Never>()
 
    internal updatedPublisher: AnyPublisher<Update, Never> {
        self.updatedSubect.eraseToAnyPublisher()
    }
 
    private func someUpdateFunction() {
        // Do some jobs
        NotificationCenter.default.post(name: Self.notificationName, object: self, userInfo: ["update": update])
        self.updateSubject.send(update)
    }
}
 
final class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        DataManager.shared.updatedPublisher
            .receive(on: DispatchQueue.main)
            .sink { [weak self] updatedInfo in
                // Do Some Logic..
            }
            .store(in: &self.cancellables)
    }
}
 

์—ฌ๊ธฐ์„œ ๋ฐฐ์šธ๋งŒํ•œ ์ ์€ ๋‘๊ฐœ์ด๋‹ค.

  1. Protocol์„ ์‚ฌ์šฉํ•ด์„œ interface๋ฅผ ๋งŒ๋“  ๋’ค์— ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค.
  2. eraseToAnyPublisher๋ฅผ ํ†ตํ•ด์„œ ์‚ฌ์šฉํ•˜๋Š” ์ชฝ์—์„œ๋Š” ์–ด๋–ค Publisher ํƒ€์ž…์ธ์ง€ ์•Œ์ง€ ๋ชปํ•˜๊ฒŒ ํ•  ์ˆ˜ ์žˆ๋‹ค. ์ฆ‰, ์ˆ˜๋™์ ์œผ๋กœ ๋งŒ๋“ค์–ด๋ฒ„๋ฆด ์ˆ˜ ์žˆ๋‹ค.

์ฝ”๋“œ๋Š” ๋ณ„๊ฒŒ ์—†์ง€๋งŒ, ๋ฐฐ์šธ์ ์ด ์žˆ๋Š” ์ฝ”๋“œ์ด๋‹ค.

์‹ค์ œ ์‚ฌ์šฉ์˜ˆ

NotificationCenter.default
    .publisher(for: UIDevice.orientationDidChangeNotification)
    .filter { _ in UIDevice.current.orientation == .portrait }
    .sink { _ in print("Orientation changed to portrait!") }

๋งˆ๋ฌด๋ฆฌ

์•„์ง์€ Combine์— ๋Œ€ํ•ด์„œ ์ œ๋Œ€๋กœ ๊ณต๋ถ€ํ•˜์ง€ ๋ชปํ•ด์„œ ์ž˜ ์•Œ์ง€ ๋ชปํ•˜์ง€๋งŒ, ๋‹น๋ถ„๊ฐ„ ๋ฐ”๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒƒ์„ ๊ธฐ์ค€์œผ๋กœ ์ •๋ฆฌํ•˜๊ณ  ์žˆ๋‹ค. ์ถ”ํ›„ Network, Error Handling, Operator๋“ฑ์— ๋Œ€ํ•ด ๊ณต๋ถ€ํ•ด์„œ ๊ธ€์„ ์ž‘์„ฑํ•ด์•ผ ํ•  ๋“ฏํ•˜๋‹ค. ๋!