Swift・iOS

Swiftを中心に学んだことを記録に残すブログです。技術に関係ない記事もたまに書いています。

【Combine】NotificationCenterでのCombineの利用

 

はじめに

NotificationCenterでのCombineの利用に関して、公式ドキュメントはもちろん外部の記事もいくつかあるのですが、全体の処理が見渡せる(実際に動かせる)サンプルコードが少なかったので、Combineを使わないパターンと使うパターンそれぞれのサンプルコードを作ってみました。

 

開発環境

 

本題

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のドキュメントで全体の実装が載っていることは少ないので、今後も自分でサンプルコードを作ることがあれば記事に残していこうと思います。

 

参考