-
Notifications
You must be signed in to change notification settings - Fork 21
Closed
Labels
enhancementNew feature or requestNew feature or request
Description
With #13's addition of @Init(assignee:type:), MemberwiseInit's @Init became expressive enough to support property-wrapped members1.
But, MemberwiseInit should provide a cleaner way to initialize properties wrapped by property wrappers. Further, @Init has become burdened by some seldomly needed parameters and is now Xcode autocomplete-unfriendly. We can improve the situation somewhat.
Here are the new macro definitions:
@Initfor standard property initialization behavior.@InitWrapperto initialize the wrapper of a property-wrapped property.@InitRawdirectly exposes the full configurability of the macro.
// An escape hatch that embraces the "template" nature of the macro and directly exposes it's configuration.
// 6 arguments
public macro InitRaw(
_ accessLevel: AccessLevelConfig? = nil,
assignee: String? = nil,
default: Any? = nil, // forward looking
escaping: Bool? = nil,
label: String? = nil,
type: Any.Type? = nil
) = …
// To simplify common usage, forgo 'assignee' and 'type'.
// 4 arguments
public macro Init(
_ accessLevel: AccessLevelConfig? = nil,
default: Any? = nil, // forward looking
escaping: Bool? = nil,
label: String? = nil
) = …
// Use the 'assignee' of 'self._\(#propertyName)'.
// 5 arguments
public macro InitWrapper(
_ accessLevel: AccessLevelConfig? = nil,
default: Any? = nil, // forward looking
escaping: Bool? = nil,,
label: String? = nil,
type: Any.Type // NB: 'type' is required because it can't be inferred, and will always be different than that of the wrapped property
) = …Example:
import SwiftUI
@propertyWrapper
struct Logged<Value> {
var wrappedValue: Value {
didSet {
print("Logged: \(wrappedValue)")
}
}
init(wrappedValue: Value) {
self.wrappedValue = wrappedValue
}
}
// NB: Some property wrappers require initialization of the property
// wrapper itself, hence `@InitWrapper`. Here, we want Logged to be
// initialized without triggering its side effects (logging).
@MemberwiseInit(.public)
public struct CounterView: View {
// @Logged: InitWrapper
@InitWrapper(.public, default: "Blob", type: Logged<String>)
@Logged
var name1: String
// @Binding: InitWrapper
@InitWrapper(.public, type: Binding<Int>)
@Binding
var count1: Int
// @Logged: InitRaw
@InitRaw(.public, assignee: "self._name1", default: "Blob", type: Logged<String>)
@Logged
var name2: String
// @Binding: InitRaw
@InitRaw(.public, assignee: "self._count1", type: Binding<Int>)
@Binding
var count2: Int
// @State
@Init(.public)
@State var isOn = false
var body: some View { … }
}swift-memberwise-init-macro version information
0.2.0
Footnotes
-
I think
@Init(assignee:type:)provides complete (if awkward) support for initializing property wrappers. If I'm wrong, I'd love to hear about it. ↩
Metadata
Metadata
Assignees
Labels
enhancementNew feature or requestNew feature or request