Reputation: 12972
When you define your own property wrapper you must specify a non-static property named 'wrappedValue'. For example:
@propertyWrapper
struct MyPropertyWrapper<Value> {
var value: Value
}
with the code above the compiler complains that:
Property wrapper type 'MyPropertyWrapper' does not contain a non-static property named 'wrappedValue'
So, you can fix the error simply doing:
@propertyWrapper
struct MyPropertyWrapper<Value> {
var value: Value
var wrappedValue: Value {
get {
value
}
set {
value = newValue
}
}
}
Just to make some examples this is true for @State
:
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
@propertyWrapper public struct State<Value> : DynamicProperty {
/// The current state value.
public var wrappedValue: Value { get nonmutating set }
}
the same for @Binding
:
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
@propertyWrapper @dynamicMemberLookup public struct Binding<Value> {
/// The value referenced by the binding. Assignments to the value
/// will be immediately visible on reading (assuming the binding
/// represents a mutable location), but the view changes they cause
/// may be processed asynchronously to the assignment.
public var wrappedValue: Value { get nonmutating set }
}
and so forth. But the @Published
property wrapper doesn't have a wrapped value:
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
@propertyWrapper public struct Published<Value> {
/// Initialize the storage of the Published property as well as the corresponding `Publisher`.
public init(initialValue: Value)
/// A publisher for properties marked with the `@Published` attribute.
public struct Publisher : Publisher {
/// The kind of values published by this publisher.
public typealias Output = Value
/// The kind of errors this publisher might publish.
///
/// Use `Never` if this `Publisher` does not publish errors.
public typealias Failure = Never
/// This function is called to attach the specified `Subscriber` to this `Publisher` by `subscribe(_:)`
///
/// - SeeAlso: `subscribe(_:)`
/// - Parameters:
/// - subscriber: The subscriber to attach to this `Publisher`.
/// once attached it can begin to receive values.
public func receive<S>(subscriber: S) where Value == S.Input, S : Subscriber, S.Failure == Published<Value>.Publisher.Failure
}
/// The property that can be accessed with the `$` syntax and allows access to the `Publisher`
public var projectedValue: Published<Value>.Publisher { mutating get }
}
I'm missing something for sure here, since the compiler won't let you create a property wrapper without the wrappedValue
. What's the difference in this case respect to the other property wrappers?
Upvotes: 12
Views: 2957
Reputation: 114875
The code you have shown isn't the actual implementation of @Published
- It is merely the publicly visible interface. If you paste that code into Xcode you will get the same error regarding wrappedValue
among others; That code doesn't compile.
wrappedValue
has an access level of internal
- So we can assume that the actual implementation of @Published
declares something like internal var wrappedValue:Value
. This satisfies the property wrapper requirement but means that wrappedValue
is not visible outside of its framework.
Upvotes: 9