add iOS
This commit is contained in:
+125
@@ -0,0 +1,125 @@
|
||||
import Dispatch
|
||||
import Foundation
|
||||
|
||||
/// A type that determines when `ValueObservation` notifies its fresh values.
|
||||
///
|
||||
/// ## Topics
|
||||
///
|
||||
/// ### Built-In Schedulers
|
||||
///
|
||||
/// - ``async(onQueue:)``
|
||||
/// - ``immediate``
|
||||
/// - ``AsyncValueObservationScheduler``
|
||||
/// - ``ImmediateValueObservationScheduler``
|
||||
public protocol ValueObservationScheduler {
|
||||
/// Returns whether the initial value should be immediately notified.
|
||||
///
|
||||
/// If the result is true, then this method was called on the main thread.
|
||||
func immediateInitialValue() -> Bool
|
||||
|
||||
func schedule(_ action: @escaping () -> Void)
|
||||
}
|
||||
|
||||
extension ValueObservationScheduler {
|
||||
func scheduleInitial(_ action: @escaping () -> Void) {
|
||||
if immediateInitialValue() {
|
||||
action()
|
||||
} else {
|
||||
schedule(action)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - AsyncValueObservationScheduler
|
||||
|
||||
/// A scheduler that asynchronously notifies fresh value of a `DispatchQueue`.
|
||||
public struct AsyncValueObservationScheduler: ValueObservationScheduler {
|
||||
var queue: DispatchQueue
|
||||
|
||||
public init(queue: DispatchQueue) {
|
||||
self.queue = queue
|
||||
}
|
||||
|
||||
public func immediateInitialValue() -> Bool { false }
|
||||
|
||||
public func schedule(_ action: @escaping () -> Void) {
|
||||
queue.async(execute: action)
|
||||
}
|
||||
}
|
||||
|
||||
extension ValueObservationScheduler where Self == AsyncValueObservationScheduler {
|
||||
/// A scheduler that asynchronously notifies fresh value of the
|
||||
/// given `DispatchQueue`.
|
||||
///
|
||||
/// For example:
|
||||
///
|
||||
/// ```swift
|
||||
/// let observation = ValueObservation.tracking { db in
|
||||
/// try Player.fetchAll(db)
|
||||
/// }
|
||||
///
|
||||
/// let cancellable = try observation.start(
|
||||
/// in: dbQueue,
|
||||
/// scheduling: .async(onQueue: .main),
|
||||
/// onError: { error in ... },
|
||||
/// onChange: { (players: [Player]) in
|
||||
/// print("fresh players: \(players)")
|
||||
/// })
|
||||
/// ```
|
||||
///
|
||||
/// - warning: Make sure you provide a serial queue, because a
|
||||
/// concurrent one such as `DispachQueue.global(qos: .default)` would
|
||||
/// mess with the ordering of fresh value notifications.
|
||||
public static func async(onQueue queue: DispatchQueue) -> AsyncValueObservationScheduler {
|
||||
AsyncValueObservationScheduler(queue: queue)
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - ImmediateValueObservationScheduler
|
||||
|
||||
/// A scheduler that notifies all values on the main `DispatchQueue`. The
|
||||
/// first value is immediately notified when the `ValueObservation`
|
||||
/// is started.
|
||||
public struct ImmediateValueObservationScheduler: ValueObservationScheduler, Sendable {
|
||||
public init() { }
|
||||
|
||||
public func immediateInitialValue() -> Bool {
|
||||
GRDBPrecondition(
|
||||
Thread.isMainThread,
|
||||
"ValueObservation must be started from the main thread.")
|
||||
return true
|
||||
}
|
||||
|
||||
public func schedule(_ action: @escaping () -> Void) {
|
||||
DispatchQueue.main.async(execute: action)
|
||||
}
|
||||
}
|
||||
|
||||
extension ValueObservationScheduler where Self == ImmediateValueObservationScheduler {
|
||||
/// A scheduler that notifies all values on the main `DispatchQueue`. The
|
||||
/// first value is immediately notified when the `ValueObservation`
|
||||
/// is started.
|
||||
///
|
||||
/// For example:
|
||||
///
|
||||
/// ```swift
|
||||
/// let observation = ValueObservation.tracking { db in
|
||||
/// try Player.fetchAll(db)
|
||||
/// }
|
||||
///
|
||||
/// let cancellable = try observation.start(
|
||||
/// in: dbQueue,
|
||||
/// scheduling: .immediate,
|
||||
/// onError: { error in ... },
|
||||
/// onChange: { (players: [Player]) in
|
||||
/// print("fresh players: \(players)")
|
||||
/// })
|
||||
/// // <- here "fresh players" is already printed.
|
||||
/// ```
|
||||
///
|
||||
/// - important: this scheduler requires that the observation is started
|
||||
/// from the main queue. A fatal error is raised otherwise.
|
||||
public static var immediate: ImmediateValueObservationScheduler {
|
||||
ImmediateValueObservationScheduler()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user