Skip to content

Instantly share code, notes, and snippets.

@fxm90
Last active December 5, 2022 15:15
Show Gist options
  • Save fxm90/68e2cc3cd6b63751c225b1e1249088cc to your computer and use it in GitHub Desktop.
Save fxm90/68e2cc3cd6b63751c225b1e1249088cc to your computer and use it in GitHub Desktop.
Extension for "NotificationCenter" to observe a notification just once and directly unsubscribe.
//
// NotificationCenter+ObserveOnce.swift
//
// Created by Felix Mau on 18.10.20.
// Copyright © 2020 Felix Mau. All rights reserved.
//
import UIKit
extension NotificationCenter {
/// Adds an observer to the given notification center, which fires just once.
///
/// Note:
/// - Same parameters as "addObserver", but with default properties
/// See http://apple.co/2zZIYJB for details.
///
/// Parameters:
/// - name: The name of the notification for which to register the observer
/// - object: The object whose notifications the observer wants to receive
/// - queue: The operation queue to which block should be added.
/// - block: The block to be executed when the notification is received.
func observeOnce(forName name: NSNotification.Name?,
object obj: Any? = nil,
queue: OperationQueue? = nil,
using block: @escaping (Notification) -> Swift.Void) {
var observer: NSObjectProtocol?
observer = addObserver(forName: name,
object: obj,
queue: queue) { [weak self] notification in
// Here we directly remove the observer, so this closure will be executed just once.
self?.removeObserver(observer!)
block(notification)
}
}
}
@DasserBasyouni
Copy link

DasserBasyouni commented Dec 5, 2022

In addition to @fxm90 answer, To avoid the sink() warning (Result of call to 'sink(receiveValue:)' is unused), You can use:

import Foundation
import Combine

// Source + TestCase: https://gist.github.com/fxm90/68e2cc3cd6b63751c225b1e1249088cc
extension NotificationCenter {
    /// Adds an observer to the given notification center, which fires just once.
    ///
    /// Note:
    ///  - Same parameters as "addObserver", but with default properties
    ///    See http://apple.co/2zZIYJB for details.
    ///
    /// Parameters:
    ///  - name:   The name of the notification for which to register the observer
    ///  - queue:  The operation queue to which block should be added.
    ///  - block:  The block to be executed when the notification is received.
    func observeOnce(forName name: NSNotification.Name,
                     queue: OperationQueue? = nil,
                     using block: @escaping (Notification) -> Swift.Void) {
        
        var cancellable: AnyCancellable?
        cancellable = NotificationCenter.default
            .publisher(for: name)
            .receive(on: queue ?? OperationQueue.main)
            .first()
            .sink { 
                block($0) 
                cancellable?.cancel()
            }
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment