Files
swift-composable-architectu…/Sources/ComposableArchitecture/SharedState/PersistenceKey.swift
Brandon Williams 54eb417336 Make 'didSet' main actor. (#3206)
* Make 'didSet' main actor.

* tests for AppStorageKey

* wip

* tests

* clean up

* Update Sources/ComposableArchitecture/SharedState/PersistenceKey/AppStorageKey.swift

* Update Sources/ComposableArchitecture/SharedState/PersistenceKey/AppStorageKeyPathKey.swift

* try working around CI problem

* Added NB

* wip

* Update MigratingTo1.11.md

---------

Co-authored-by: Stephen Celis <stephen@stephencelis.com>
2024-07-17 08:57:43 -07:00

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> {
/// A type that can be loaded or subscribed to in an external system.
associatedtype Value
/// 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()
}
}
}