Skip to content

samsonjs/AsyncMonitor

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

10 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

AsyncMonitor

0 dependencies!

Overview

AsyncMonitor is a Swift library that provides a simple and easy-to-use way to manage Swift concurrency Tasks that observe async sequences. The AsyncMonitor class allows you to create tasks that observe streams and call the given closure with each new value, and optionally also with a context parameter so you don't have to manage its lifetime.

It uses a Swift Task to ensure that all resources are properly cleaned up when the AsyncMonitor is cancelled or deallocated.

That's it. It's pretty trivial. I just got tired of writing it over and over, mainly for notifications. You still have to map your Notifications to something sendable, which brings me to another point. This package pairs nicely with NotificationSmuggler for a complete notification handling system in the Swift 6 concurrency world.

Usage

The simplest example uses a closure that receives the notification. The closure is async so you can await in there if you need to.

import AsyncMonitor

class SimplestVersion {
    let cancellable = NotificationCenter.default
        .notifications(named: .NSCalendarDayChanged)
        .map(\.name)
        .monitor { _ in
            print("The date is now \(Date.now)")
        }
}

This example uses the context parameter to avoid reference cycles with self.

class WithContext {
    var cancellables = Set<AnyAsyncCancellable>()

    init() {
        NotificationCenter.default
            .notifications(named: .NSCalendarDayChanged)
            .map(\.name)
            .monitor(context: self) { _self, _ in
                _self.dayChanged()
            }.store(in: &cancellables)
    }

    func dayChanged() {
        print("The date is now \(Date.now)")
    }
}

Combine

Working with Combine publishers is trivial thanks to AnyPublisher.values.

import Combine

class CombineExample {
    var cancellables = Set<AnyAsyncCancellable>()

    init() {
        Timer.publish(every: 1.0, on: .main, in: .common)
            .autoconnect()
            .values
            .monitor { date in
                print("Timer fired at \(date)")
            }
            .store(in: &cancellables)
    }
}

Key-Value Observing (KVO) extension

When you need to observe an object that uses KVO there's an extension method you can use to monitor it:

class KVOExample {
    var cancellables = Set<AnyAsyncCancellable>()

    init() {
        let progress = Progress(totalUnitCount: 42)
        progress.monitorValues(for: \.fractionCompleted) { fraction in
            print("Progress is \(fraction.formatted(.percent))%")
        }.store(in: &cancellables)
    }
}

Installation

The only way to install this package is with Swift Package Manager (SPM). Please file a new issue or submit a pull-request if you want to use something else.

Supported Platforms

This package is supported on iOS 17.0+ and macOS 14.0+.

Xcode

When you're integrating this into an app with Xcode then go to your project's Package Dependencies and enter the URL https://github.com/samsonjs/AsyncMonitor and then go through the usual flow for adding packages.

Swift Package Manager (SPM)

When you're integrating this using SPM on its own then add this to the list of dependencies your Package.swift file:

.package(url: "https://github.com/samsonjs/AsyncMonitor.git", .upToNextMajor(from: "0.3.1"))

and then add "AsyncMonitor" to the list of dependencies in your target as well.

License

Copyright © 2025 Sami Samhuri [email protected]. Released under the terms of the MIT License.

About

Easily monitor async sequences using Swift concurrency

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages