somu
(somu)
1
Overview:
I have a Property Wrapper Coordinates. In the class Car I am using the Coordinates Property Wrapper.
Questions:
- How can I initialise
Coordinates using Car's initialiser ?
- How to make
_coordinates accessible ? (I am not sure what is responsible for _coordinates)
- Is there any documentation on the above ? Most examples I saw were using
struct where the compiler generates / synthesises initialisers for the properties.
Note: I have added comments with the compilation errors that I am getting while attempting to do the above.
Code:
@propertyWrapper
struct Coordinates {
private var point : CGPoint
var wrappedValue : (Double, Double) {
get {
return (Double(point.x), Double(point.y))
}
set {
point = .init(x:newValue.0, y:newValue.1)
}
}
var value : CGPoint {
return point
}
init(_ tuple: (Double, Double) = (0, 0)) {
self.point = .init(x: tuple.0, y: tuple.1)
}
}
class Car {
@Coordinates var coordinates : (Double, Double)
init(tuple: (Double, Double)) {
//Compilation Error: 'self' used in property access 'coordinates' before all stored properties are initialized
self.coordinates = tuple
}
}
let car1 = Car(tuple: (10.22, 20.33))
//Compilation Error: _coordinates' is inaccessible due to 'private' protection level
print(car1._coordinates)
How can I initialise Coordinates using Car 's initialiser ?
init(tuple: (Double, Double)) {
self._coordinates = _Coordinates(tuple)
}
How to make _coordinates accessible ? (I am not sure what is responsible for _coordinates)
Accessible from where? Currently it's not possible to access the property wrapper outside the type because it automatically is a private stored property.
You could however write a different property and expose the wrapper.
var exposedCoordinates: Coordinates {
_coordinates
}
Is there any documentation on the above ? Most examples I saw were using struct where the compiler generates / synthesises initialisers for the properties.
The best documentation is the proposal itself: https://github.com/apple/swift-evolution/blob/master/proposals/0258-property-wrappers.md
Alternative solution, just make everything manually!
class Car {
// FIXME: Change to `internal(wrapper) @Coordinates` when possible
internal var _coordinates: Coordinates
var coordinates: (Double, Double) {
get {
_coordinates.wrappedValue
}
set {
_coordinates.wrappedValue = newValue
}
}
init(tuple: (Double, Double)) {
self._coordinates = Coordinates(tuple)
}
}
1 Like
somu
(somu)
3
@DevAndArtist Thank you so much for the detailed explanation and reference link.
I suppose the reason for the initialisation compilation error was because I was trying to set a computed property (wrappedValue) in the initialiser before self.point was set.
The following code from the proposal documentation explains the use of _ variable:
@Lazy var foo = 1738 translates to:
private var _foo: Lazy<Int> = Lazy<Int>(wrappedValue: 1738)
var foo: Int {
get { return _foo.wrappedValue }
set { _foo.wrappedValue = newValue }
}
There is a small typo in the initialiser _Coordinates(tuple), I suppose it was Coordinates(tuple)
1 Like
somu
(somu)
4
@DevAndArtist
Just wondering if it would be possible for the compiler to infer the data type while declaring a property that uses a non-generic property wrapper.
Example 1 (works ok):
//(Double, Double) has to match the data type of the `wrappedValue`
@Coordinates var coordinates : (Double, Double)
Example 2 (compilation error):
//Compilation Error:
//Property type 'Int' does not match that of the 'wrappedValue' property of its wrapper type 'Coordinate'
@Coordinate var coordinates : Int
Based on the compilation error message, it seems like the compiler is expecting wrappedValue's data type.
Avi
5
It could, in theory, though I am not sure I would like to see
@Wrapper var x
in a type definition.
1 Like
somu
(somu)
6
Thanks @Avi for the explanation.
I just realised it is possible to do the following:
@Coordinates((0, 0)) var coordinates
bzamayo
(Benjamin Mayo)
7
As this is in the Using Swift category ... in this particular case I’m not really sure why are you using a property wrapper at all? It might be worth taking a moment to double-check this is what you want.
I think the code would be cleaner and clearer if Coordinates was just a simple struct with two properties, or you could consider using CGPoint directly.
1 Like
somu
(somu)
8
Thanks @bzamayo, you are right, may be the example wasn't good.
I am learning to use property wrapper, so thought I would test it with an example.
1 Like