Welcome back to Swift Property Wrappers exploration! In my previous article we’ve started talking about its internal implementation and tried to grasp the intuition behind this feature. Just to recap, we have figured out that the property wrapper (PW) is basically a regular struct, instance of which invisibly substitutes the instance of other properties (wrapped properties) in any other struct or class. As an example we’ve introduced the struct State (the PW-struct) that prints out its only property wrappedValue once it is set, and we are using it with properties of Dashboard struct.

Any struct is eligible to be a PW-struct as long as it has the stored property with the exact name wrappedValue. You mark it with @propertyWrapper attribute, and now the name of this struct itself is turned to a brand new attribute (in our example — @Printed), which you use to mark stored properties of any other structs and classes, as long as type of this property is the same as type of wrappedValue in PW-struct. So what effect does this attribute cause? This might appear a bit tangled at first sight, but consider this way of reading the code with PWs: just keep in mind that there is no longer a stored Double value of altitude, but instead you have another property of type Printed (it is indeed there, it’s implicitly synthesized by compiler, but still explicitly accessible as _altitude), and your original altitude is now nothing more than a shortcut way of accessing _altitude.wrappedValue.

If there are still some blank spaces for you in what property wrappers actually are, I’d recommend to start from the first article. It describes all this in more details, as well as the exact compiler mechanism of how the instance of Printed hooked up to Dashboard.altitude. If you’ve already absorbed this, let’s go on.

Initialization

The only thing about this mechanism we’ve left aside is initialization, and it is definitely not something we can ignore. This hidden PW-struct instance (like _altitude) should de of course initialized. And as before, this part has nothing really cryptic, although there are some pitfalls to be aware of.

We’ll dive into all this in a minute, but let’s first remember the basics. Any stored instance property in Swift can be initialized in two alternative ways: it either can be assigned with initial (default) value right next to its definition, or it can be set in initializer.Althought this is not an official terminology of Apple documentation, let’s for brevity call these two ways static and dynamic respectively. First way is happening in static realm, with no access to any non-static memory. Second one allows you to use any dynamic value passed through initializer arguments.

So, the static initialization of property-wrapped property may look similar to one of regular (not property-wrapped) property:

But we already know that altitude: Double itself is just a computed property proxying wrappedValue of _altitude: Printed<Double>. So setting its value in this manner kind of makes no sense. What really takes place backstage is the following declaration:

private var _altitude = Printed<Double>(wrappedValue: 10)

So the compiler actually takes this initial value of 10 and puts is as an argument of default initializer. This default initializer any struct in Swift gets for free, and of course the PW-struct is not an exception.But note that if you create some other initializer in Printed you automatically lose the default one (this is also a general rule in Swift, not something specific for PW). And if there is no this exact initializer with the first argument named exactly wrappedValue, you won’t be able to assign initial value this way.

#xcode #programming #ios #mobile #swift

Swift Property Wrappers Unwrapped: Part 2
1.15 GEEK