Last active
December 16, 2022 19:37
-
-
Save albertbori/4228bf583e3121cdd1e3403bb3f25bde to your computer and use it in GitHub Desktop.
Swift Property Wrapper Implicit Initialization Scenarios
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
This example shows how a simple property wrapper can be declared and initialized. | |
*/ | |
@propertyWrapper | |
struct ExampleA<Value> { | |
private var value: Value | |
var wrappedValue: Value { | |
get { value } | |
set { value = newValue } | |
} | |
init(wrappedValue: Value) { | |
value = wrappedValue | |
} | |
} | |
struct ExampleAView: View { | |
@ExampleA var value: String | |
var body: some View { | |
Text(value) | |
} | |
} | |
struct ExampleAParentView: View { | |
var body: some View { | |
// default property wrapper initializer inferred from `init(wrappedValue: Value)` | |
ExampleAView(value: "Cool") | |
// not allowed, despite being allowed in other examples: | |
// ExampleAView(value: .init(wrappedValue: "Cool")) | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
This example shows how a simple property wrapper can be extended to have an ancillary value. | |
It also shows how this affects how it is declared and initialized. | |
It also shows the limitations of being unable to split the value initialization from the declaration. | |
*/ | |
@propertyWrapper | |
struct ExampleB<Value> { | |
private var value: Value | |
private var myValue: String | |
var wrappedValue: Value { | |
get { value } | |
set { value = newValue } | |
} | |
var projectedValue: String { myValue } | |
init(wrappedValue: Value, myValue: String) { | |
value = wrappedValue | |
self.myValue = myValue | |
} | |
} | |
struct ExampleBView: View { | |
@ExampleB(myValue: "Bar") var value: String = "Foo" | |
// not allowed (Missing argument for parameter 'wrappedValue' in call): | |
// @ExampleB(myValue: "Bar") var value: String | |
var body: some View { | |
Text(value) // Foo | |
Text($value) // Bar | |
} | |
} | |
struct ExampleB2View: View { | |
// note: this declaration implicitly relies on the view initializer to specify the details: | |
@ExampleB var value: String | |
var body: some View { | |
Text(value) | |
Text($value) | |
} | |
} | |
struct ExampleBParentView: View { | |
var body: some View { | |
// has a default value, so no value required: | |
ExampleBView() | |
// default property wrapper initializer inferred from `init(wrappedValue: Value, myValue: String)`: | |
ExampleBView(value: "Foo") | |
// manually initializing the property wrapper: | |
ExampleB2View(value: .init(wrappedValue: "Foo", myValue: "Bar")) | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
This example shows how a property wrapper with an ancillary value can utilize default values. | |
*/ | |
@propertyWrapper | |
struct ExampleC<Value> { | |
private var value: Value | |
private var myValue: String | |
var wrappedValue: Value { | |
get { value } | |
set { value = newValue } | |
} | |
var projectedValue: String { myValue } | |
init(wrappedValue: Value, myValue: String) { | |
value = wrappedValue | |
self.myValue = myValue | |
} | |
} | |
extension ExampleC where Value: ExpressibleByStringLiteral { | |
init(myValue: String) { | |
self.init(wrappedValue: "someDefaultValue", myValue: myValue) | |
} | |
} | |
struct ExampleCView: View { | |
@ExampleC(myValue: "Bar") var value: String = "Foo" | |
var body: some View { | |
Text(value) // Foo | |
Text($value) // Bar | |
} | |
} | |
struct ExampleC2View: View { | |
//note: This allows you to split the declaration between the parent initalizer and this property wrapper declaration | |
@ExampleC(myValue: "Bar") var value: String | |
var body: some View { | |
Text(value) // someDefaultValue | |
Text($value) // Bar | |
} | |
} | |
struct ExampleC3View: View { | |
@ExampleC var value: String | |
var body: some View { | |
Text(value) | |
Text($value) | |
} | |
} | |
struct ExampleCParentView: View { | |
var body: some View { | |
ExampleCView() | |
ExampleCView(value: "Foo") | |
ExampleC2View() | |
// not allowed: | |
// ExampleC2View(value: "Foo") | |
ExampleC2View(value: .init(myValue: "Bar")) | |
ExampleC2View(value: .init(wrappedValue: "Foo", myValue: "Bar")) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment