はじめに
NotificationCenterでのCombineの利用に関して、公式ドキュメントはもちろん外部の記事もいくつかあるのですが、全体の処理が見渡せる(実際に動かせる)サンプルコードが少なかったので、Combineを使わないパターンと使うパターンそれぞれのサンプルコードを作ってみました。
開発環境
- macOS Big Sur 11.4
- Xcode 12.5.1
- Swift 5.4.2
本題
Combineを使わないパターン
"addObserver(_:selector:name:object:)"を使うことで通知を監視する。
※参考:
https://developer.apple.com/documentation/foundation/notificationcenter/1415360-addobserver
サンプルコード
ContentView.swift
import SwiftUI import NotificationCenter struct ContentView: View {
private let sampleNotification = Notification.Name("sampleNotification") init() { _ = NotificationCenter.default.addObserver(forName: sampleNotification, object: nil, queue: nil) { _ in print("Receive notification") } } var body: some View { Button(action: { NotificationCenter.default.post(name: sampleNotification, object: nil) }, label: { Text("Send notification") }) } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } }
Combineを使うパターン
"publisher(for:object:)"を使う。
※参考:
https://developer.apple.com/documentation/foundation/notificationcenter/3329353-publisher
サンプルコード
ContentView.swift
import SwiftUI import Combine struct ContentView: View { private let sampleNotification = Notification.Name("sampleNotification") private var cancellable: AnyCancellable? init() { cancellable = NotificationCenter.default.publisher(for: sampleNotification, object: nil) .sink(receiveCompletion: { completion in switch completion { case .finished: print("finished") case .failure(let error): print("error \(error.localizedDescription)") } }, receiveValue: { _ in print("Receive notification") }) } var body: some View { Button(action: { NotificationCenter.default.post(name: sampleNotification, object: nil) }, label: { Text("Send notification") }) } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } }
補足
SwiftUIのViewで通知を受け取る場合は、"onReceive(_:perform:)"を使う方が簡潔に実装できます。
※参考:
【SwiftUI】NotificationCenterの通知をSwiftUIのViewで受け取る方法 - Swift・iOS
公式ドキュメント(https://developer.apple.com/documentation/combine/receiving-and-handling-events-with-combine)の"Connect a Publisher to a Subscriber"に記載された内容のイメージがつくように上記のサンプルを作ったのですが、SwiftUIのViewに実装したことでややこしくなってしまいました・・・。
おわりに
Combineのドキュメントで全体の実装が載っていることは少ないので、今後も自分でサンプルコードを作ることがあれば記事に残していこうと思います。
参考
-
https://developer.apple.com/documentation/combine/receiving-and-handling-events-with-combine
-
https://developer.apple.com/documentation/foundation/notificationcenter
-
https://developer.apple.com/documentation/foundation/notificationcenter/1415360-addobserver
-
https://developer.apple.com/documentation/foundation/notificationcenter/3329353-publisher
-
https://developer.apple.com/documentation/combine/anycancellable
-
https://developer.apple.com/documentation/swiftui/view/onreceive(_:perform:)
-
https://developer.apple.com/documentation/combine/routing-notifications-to-combine-subscribers
-
Combine Framework Beginner Tutorial in Swift - Working with NotificationCenter - Swift Pal
-
[Swift] はじめてのCombine | Apple製の非同期フレームワークを使ってみよう | DevelopersIO