Skip to content

Instantly share code, notes, and snippets.

@YusukeHosonuma
Created August 15, 2020 02:07
Show Gist options
  • Save YusukeHosonuma/0a39266dd5c2232d6d0a42f826adb8e6 to your computer and use it in GitHub Desktop.
Save YusukeHosonuma/0a39266dd5c2232d6d0a42f826adb8e6 to your computer and use it in GitHub Desktop.
NWPathMonitor を Combine の Publisher として扱えるようにする拡張
import SwiftUI
import Network
final class ViewModel: ObservableObject {
@Published var status: NWPath.Status = .satisfied
init() {
NWPathMonitor()
.publisher()
.map { $0.status }
.assign(to: &$status)
}
}
struct ContentView: View {
@StateObject var viewModel = ViewModel()
var body: some View {
if viewModel.status == .satisfied {
Text("オンラインなう!")
} else {
Text("オフラインだぉ・・・")
}
}
}
import Combine
import Foundation
import Network
extension NWPathMonitor {
func publisher(queue: DispatchQueue = DispatchQueue.main) -> NWPathMonitor.Publisher {
Publisher(monitor: self, queue: queue)
}
final class Subscription<S: Subscriber>: Combine.Subscription where S.Input == NWPath {
private let subscriber: S
private let monitor: NWPathMonitor
private let queue: DispatchQueue
private var isStarted = false
init(subscriber: S, monitor: NWPathMonitor, queue: DispatchQueue) {
self.subscriber = subscriber
self.monitor = monitor
self.queue = queue
}
func request(_ demand: Subscribers.Demand) {
precondition(demand == .unlimited, "This subscription is only supported to `Demand.unlimited`.")
guard !isStarted else { return }
isStarted = true
monitor.pathUpdateHandler = { [unowned self] path in
_ = self.subscriber.receive(path)
}
monitor.start(queue: queue)
}
func cancel() {
monitor.cancel()
}
}
struct Publisher: Combine.Publisher {
typealias Output = NWPath
typealias Failure = Never
private let monitor: NWPathMonitor
private let queue: DispatchQueue
init(monitor: NWPathMonitor, queue: DispatchQueue) {
self.monitor = monitor
self.queue = queue
}
func receive<S>(subscriber: S) where S : Subscriber, Self.Failure == S.Failure, Self.Output == S.Input {
let subscription = Subscription(subscriber: subscriber, monitor: monitor, queue: queue)
subscriber.receive(subscription: subscription)
}
}
}
@YusukeHosonuma
Copy link
Author

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