Skip to content

Instantly share code, notes, and snippets.

@helje5
Created December 29, 2025 19:27
Show Gist options
  • Select an option

  • Save helje5/44514280956946532629742e381fda42 to your computer and use it in GitHub Desktop.

Select an option

Save helje5/44514280956946532629742e381fda42 to your computer and use it in GitHub Desktop.
An async stream wrapper for NWBrowser events
//
// NWBrowserStream.swift
// AsyncNetwork
//
// Created by Helge Heß on 14.04.24.
//
import OSLog
import Network
public extension NWBrowser {
typealias Stream =
AsyncThrowingStream<Set<NWBrowser.Result.Change>, any Error>
func makeStream(queue: DispatchQueue = .main) -> Stream {
let logger =
Logger(subsystem: "de.zeezide.async.nw", category: "browser")
return AsyncThrowingStream(Stream.Element.self) { continuation in
continuation.onTermination = { [weak self] termination in
logger.debug("Browser stream terminated.")
self?.cancel()
}
self.browseResultsChangedHandler = { newResults, changes in
logger.debug("Browser stream got results: #\(changes.count).")
continuation.yield(changes)
}
self.stateUpdateHandler = { [weak self] newState in
switch newState {
case .setup: // created but not started
logger.debug("Browser has setup as new state?")
case .cancelled:
logger.debug("Browser stream got cancelled.")
continuation.finish()
case .failed(let error):
logger.error("Browser stream failed: \(error)")
continuation.finish(throwing: error)
case .ready: // started
// Yield initial results add "added"
guard let self else {
logger.error("Browser stream ready, but self is gone?")
continuation.finish()
return
}
let initial = self.browseResults
assert(initial.isEmpty, "There are browse results on startup?")
if !initial.isEmpty {
logger.debug("Browser stream, initial results: #\(initial.count)")
continuation.yield(
Set(initial.map { NWBrowser.Result.Change.added($0) }))
}
case .waiting(let error):
logger.warning("Browser waiting \(error)")
@unknown default:
logger.error(
"Unexpected State Change: \(String(describing: newState))")
}
}
self.start(queue: queue)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment