diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d693209d..9c59f14de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,10 @@ # master *Please add new entries at the top.* +1. Add primary associated types to property and binding protocols (#888, kudos to @braker1nine) 1. Fix the Carthage build checks (kudos to @mluisbrown) 1. Add dynamic library support for SPM (#886 kudos to @mluisbrown) # 7.2.0 -*Please add new entries at the top.* - 1. Change `QueueScheduler` to use unspecified QoS when QoS parameter is defaulted (#880, kudos to @jamieQ) 1. Add support for visionOS (#875, kudos to @NachoSoto) 1. Fix CI release git tag push trigger (#869, kudos to @p4checo) diff --git a/Sources/Property.swift b/Sources/Property.swift index 383313c2a..39c1142a5 100644 --- a/Sources/Property.swift +++ b/Sources/Property.swift @@ -7,6 +7,35 @@ import Glibc // FIXME: The `Error == Never` constraint is retained for Swift 4.0.x // compatibility, since `BindingSource` did not impose such constraint // due to the absence of conditional conformance. +#if swift(>=5.7) + +/// Represents a property that allows observation of its changes. +/// +/// Only classes can conform to this protocol, because having a signal +/// for changes over time implies the origin must have a unique identity. +public protocol PropertyProtocol: AnyObject, BindingSource { + /// The current value of the property. + var value: Value { get } + + /// The values producer of the property. + /// + /// It produces a signal that sends the property's current value, + /// followed by all changes over time. It completes when the property + /// has deinitialized, or has no further change. + /// + /// - note: If `self` is a composed property, the producer would be + /// bound to the lifetime of its sources. + var producer: SignalProducer { get } + + /// A signal that will send the property's changes over time. It + /// completes when the property has deinitialized, or has no further + /// change. + /// + /// - note: If `self` is a composed property, the signal would be + /// bound to the lifetime of its sources. + var signal: Signal { get } +} +#else /// Represents a property that allows observation of its changes. /// @@ -34,7 +63,20 @@ public protocol PropertyProtocol: AnyObject, BindingSource { /// bound to the lifetime of its sources. var signal: Signal { get } } +#endif +#if swift(>=5.7) +/// Represents an observable property that can be mutated directly. +public protocol MutablePropertyProtocol: PropertyProtocol, BindingTargetProvider { + associatedtype Value + + /// The current value of the property. + var value: Value { get set } + + /// The lifetime of the property. + var lifetime: Lifetime { get } +} +#else /// Represents an observable property that can be mutated directly. public protocol MutablePropertyProtocol: PropertyProtocol, BindingTargetProvider { /// The current value of the property. @@ -43,6 +85,7 @@ public protocol MutablePropertyProtocol: PropertyProtocol, BindingTargetProvider /// The lifetime of the property. var lifetime: Lifetime { get } } +#endif /// Default implementation of `BindingTargetProvider` for mutable properties. extension MutablePropertyProtocol { @@ -51,6 +94,29 @@ extension MutablePropertyProtocol { } } +#if swift(>=5.7) +/// Represents a mutable property that can be safety composed by exposing its +/// synchronization mechanic through the defined closure-based interface. +public protocol ComposableMutablePropertyProtocol: MutablePropertyProtocol { + /// Atomically performs an arbitrary action using the current value of the + /// variable. + /// + /// - parameters: + /// - action: A closure that accepts current property value. + /// + /// - returns: the result of the action. + func withValue(_ action: (Value) throws -> Result) rethrows -> Result + + /// Atomically modifies the variable. + /// + /// - parameters: + /// - action: A closure that accepts old property value and returns a new + /// property value. + /// + /// - returns: The result of the action. + func modify(_ action: (inout Value) throws -> Result) rethrows -> Result +} +#else /// Represents a mutable property that can be safety composed by exposing its /// synchronization mechanic through the defined closure-based interface. public protocol ComposableMutablePropertyProtocol: MutablePropertyProtocol { @@ -72,6 +138,7 @@ public protocol ComposableMutablePropertyProtocol: MutablePropertyProtocol { /// - returns: The result of the action. func modify(_ action: (inout Value) throws -> Result) rethrows -> Result } +#endif // Property operators. // diff --git a/Sources/UnidirectionalBinding.swift b/Sources/UnidirectionalBinding.swift index a40e7a4ae..b7b341e71 100644 --- a/Sources/UnidirectionalBinding.swift +++ b/Sources/UnidirectionalBinding.swift @@ -10,17 +10,31 @@ precedencegroup BindingPrecedence { infix operator <~ : BindingPrecedence +#if swift(>=5.7) +/// Describes a source which can be bound. +public protocol BindingSource: SignalProducerConvertible where Error == Never {} +#else /// Describes a source which can be bound. public protocol BindingSource: SignalProducerConvertible where Error == Never {} +#endif extension Signal: BindingSource where Error == Never {} extension SignalProducer: BindingSource where Error == Never {} -/// Describes an entity which be bond towards. +#if swift(>=5.7) +/// Describes an entity which be bound towards. +public protocol BindingTargetProvider { + associatedtype Value + + var bindingTarget: BindingTarget { get } +} +#else +/// Describes an entity which be bound towards. public protocol BindingTargetProvider { associatedtype Value var bindingTarget: BindingTarget { get } } +#endif extension BindingTargetProvider { /// Binds a source to a target, updating the target's value to the latest @@ -46,7 +60,7 @@ extension BindingTargetProvider { /// ```` /// /// - parameters: - /// - target: A target to be bond to. + /// - target: A target to be bound to. /// - source: A source to bind. /// /// - returns: A disposable that can be used to terminate binding before the @@ -86,7 +100,7 @@ extension BindingTargetProvider { /// ```` /// /// - parameters: - /// - target: A target to be bond to. + /// - target: A target to be bound to. /// - source: A source to bind. /// /// - returns: A disposable that can be used to terminate binding before the @@ -111,7 +125,7 @@ extension Signal.Observer { /// deinitialized, or when the source sends a `completed` event. /// /// - parameters: - /// - target: A target to be bond to. + /// - target: A target to be bound to. /// - source: A source to bind. /// /// - returns: A disposable that can be used to terminate binding before the