Let’s see a demo involving property wrapper (not real code, for proof-of-concept purpose only, the wrappedValue
part can not accomplish such task actually):
@propertyWrapper
struct DatabaseProperty<Value> {
let field: String
init(_ field: String) { self.field = field }
var wrappedValue: Value {
get { ... }
set { ... }
}
}
class People {
var id: Int
init(id: Int) { self.id = id }
@DatabaseProperty("name")
var name: String
}
So far so good! Database access is simplified:
var person = People(id: 1)
person.name // getter
person.name = "John Appleseed" // setter
For another property, age
, we want to make it read-only. With minimal effort, let’s introduce another property wrapper, @ReadOnly
:
@propertyWrapper
struct ReadOnly<Value> {
private var _value: Value
var wrappedValue: Value { _value }
init(wrappedValue: Value) { _value = wrappedValue }
}
class People {
var id: Int
init(id: Int) { self.id = id }
@DatabaseProperty("name")
var name: String
@ReadOnly
@DatabaseProperty("age")
var age: Int
}
Unfortunately, according to SR-0258:
When there are multiple, composed property wrappers, only the first (outermost) wrapper may have initializer arguments.
For implicit initialization, when there are multiple, composed property wrappers, only the first (outermost) wrapper needs to have an
init()
.
Both limitations / design decisions make above proof-of-concept code invalid.
Is there an elegant solution for the exact use case above (limit read-write property wrapper to read-only)? Two separate property wrappers (ReadWriteDatabaseProperty
and ReadOnlyDatabaseProperty
) looks less orthogonal to my eyes.
Thanks.