mirror of
https://github.com/pointfreeco/swift-composable-architecture.git
synced 2025-12-20 09:11:33 +01:00
* Address @Shared sendability. * Undo UncheckedSendable<UserDefaults>. * clean up * wip * drop AnySendable. * wip * Address `Effect.throttle` sendability (#3325) * Address effect cancellation sendability (#3326) * Address effect cancellation sendability * fix * wip * wip * Separate SendableDefaultSubscript from DefaultSubscript. * fix test * drop escaping * switch on swift 6 language mode * xcode 16 * update test * wip --------- Co-authored-by: Stephen Celis <stephen@stephencelis.com>
95 lines
3.5 KiB
Swift
95 lines
3.5 KiB
Swift
/// A type that can load and subscribe to state in an external system.
|
|
///
|
|
/// Conform to this protocol to express loading state from an external system, and subscribing to
|
|
/// state changes in the external system. It is only necessary to conform to this protocol if the
|
|
/// ``AppStorageKey``, ``FileStorageKey``, or ``InMemoryKey`` strategies are not sufficient for your
|
|
/// use case.
|
|
///
|
|
/// See the article <doc:SharingState> for more information, in particular the
|
|
/// <doc:SharingState#Custom-persistence> section.
|
|
public protocol PersistenceReaderKey<Value>: Sendable {
|
|
/// A type that can be loaded or subscribed to in an external system.
|
|
associatedtype Value: Sendable
|
|
|
|
/// A type representing the hashable identity of a persistence key.
|
|
associatedtype ID: Hashable = Self
|
|
|
|
/// The hashable identity of a persistence key.
|
|
///
|
|
/// Used to look up existing shared references associated with this persistence key.
|
|
var id: ID { get }
|
|
|
|
/// Loads the freshest value from storage. Returns `nil` if there is no value in storage.
|
|
///
|
|
/// - Parameter initialValue: An initial value assigned to the `@Shared` property.
|
|
/// - Returns: An initial value provided by an external system, or `nil`.
|
|
func load(initialValue: Value?) -> Value?
|
|
|
|
/// Subscribes to external updates.
|
|
///
|
|
/// - Parameters:
|
|
/// - initialValue: An initial value assigned to the `@Shared` property.
|
|
/// - didSet: A closure that is invoked with new values from an external system, or `nil` if the
|
|
/// external system no longer holds a value.
|
|
/// - Returns: A subscription to updates from an external system. If it is cancelled or
|
|
/// deinitialized, the `didSet` closure will no longer be invoked.
|
|
func subscribe(
|
|
initialValue: Value?,
|
|
didSet: @escaping @Sendable (_ newValue: Value?) -> Void
|
|
) -> Shared<Value>.Subscription
|
|
}
|
|
|
|
extension PersistenceReaderKey where ID == Self {
|
|
public var id: ID { self }
|
|
}
|
|
|
|
extension PersistenceReaderKey {
|
|
public func subscribe(
|
|
initialValue: Value?,
|
|
didSet: @escaping @Sendable (_ newValue: Value?) -> Void
|
|
) -> Shared<Value>.Subscription {
|
|
Shared.Subscription {}
|
|
}
|
|
}
|
|
|
|
/// A type that can persist shared state to an external storage.
|
|
///
|
|
/// Conform to this protocol to express persistence to some external storage by describing how to
|
|
/// save to and load from the external storage, and providing a stream of values that represents
|
|
/// when the external storage is changed from the outside. It is only necessary to conform to this
|
|
/// protocol if the ``AppStorageKey``, ``FileStorageKey``, or ``InMemoryKey`` strategies are not
|
|
/// sufficient for your use case.
|
|
///
|
|
/// See the article <doc:SharingState> for more information, in particular the
|
|
/// <doc:SharingState#Custom-persistence> section.
|
|
public protocol PersistenceKey<Value>: PersistenceReaderKey {
|
|
/// Saves a value to storage.
|
|
func save(_ value: Value)
|
|
}
|
|
|
|
extension Shared {
|
|
/// A subscription to a ``PersistenceReaderKey``'s updates.
|
|
///
|
|
/// This object is returned from ``PersistenceReaderKey/subscribe(initialValue:didSet:)``, which
|
|
/// will feed updates from an external system for its lifetime, or till ``cancel()`` is called.
|
|
public class Subscription {
|
|
let onCancel: () -> Void
|
|
|
|
/// Initializes the subscription with the given cancel closure.
|
|
///
|
|
/// - Parameter cancel: A closure that the `cancel()` method executes.
|
|
public init(_ cancel: @escaping () -> Void) {
|
|
self.onCancel = cancel
|
|
}
|
|
|
|
deinit {
|
|
self.cancel()
|
|
}
|
|
|
|
/// Cancels the subscription.
|
|
public func cancel() {
|
|
self.onCancel()
|
|
}
|
|
}
|
|
}
|