young
(rtSwift)
1
So this is what I got:
protocol AlignmentDescriptor {
associatedtype T: Equatable
static var alignments: [T] { get }
static func name(of alignment: T) -> String
}
struct HorizontalAlignmentDescriptor: AlignmentDescriptor {
static let alignments = [HorizontalAlignment.leading, .center, .trailing]
static func name(of alignment: HorizontalAlignment) -> String {
switch alignment {
case .leading:
return "Leading"
case .center:
return "Center"
case .trailing:
return "Trailing"
default:
fatalError("Got some unknown alignment value!!!!")
}
}
}
struct VerticalAlignmentDescriptor: AlignmentDescriptor {
static let alignments = [VerticalAlignment.top, .center, .bottom]
static func name(of alignment: VerticalAlignment) -> String {
switch alignment {
case .top:
return "Top"
case .center:
return "Center"
case .bottom:
return "Bottom"
default:
fatalError("Got some unknown alignment value!!!!")
}
}
}
struct AlignmentPicker<AD: AlignmentDescriptor>: View {
@Binding var alignment: AD.T
var body: some View {
Picker(selection: Binding<Int>(get: { AD.alignments.firstIndex(of: self.alignment)! }, set: { self.alignment = AD.alignments[$0] }),
label: Text("Choose your alignment")) {
ForEach(0..<AD.alignments.count) { index in
Text(AD.name(of: AD.alignments[index])).tag(index)
}
}.pickerStyle(SegmentedPickerStyle())
}
}
But got error:
struct ImplicitAlignmentDemo: View {
@State private var alignment: HorizontalAlignment = .trailing
var body: some View {
// Compile error at self.$alignment
// Cannot convert value of type 'Binding<HorizontalAlignment>' to expected argument type 'Binding<_>'
// 1. Arguments to generic parameter 'Value' ('HorizontalAlignment' and '_') are expected to be equal
AlignmentPicker(alignment: self.$alignment)
}
}
young
(rtSwift)
2
If I change the generic AlignmentPicker to a typealias, then no compile error:
struct AlignmentPicker: View {
typealias AD = HorizontalAlignmentDescriptor
@Binding var alignment: AD.T
var body: some View {
Picker(selection: Binding<Int>(get: { AD.alignments.firstIndex(of: self.alignment)! }, set: { self.alignment = AD.alignments[$0] }),
label: Text("Choose your alignment")) {
ForEach(0..<AD.alignments.count) { index in
Text(AD.name(of: AD.alignments[index])).tag(index)
}
}.pickerStyle(SegmentedPickerStyle())
}
}
Have I run into some sort of compiler bug?
========================================
Update:
So give the compiler a little help get pass the compile error:
struct ImplicitAlignmentJunk: View {
@State private var alignment: HorizontalAlignment = .trailing
var body: some View {
AlignmentPicker<HorizontalAlignmentDescriptor>(alignment: self.$alignment)
}
}
Should the compile be able to infer the generic type from just:
AlignmentPicker(alignment: self.$alignment)
?
Maybe the problem is type inference and Property Wrapper $?
========================================
Update2 Version:
protocol AlignmentDescriptor {
associatedtype T: Equatable
static var alignments: [T] { get }
static func name(of alignment: T) -> String
}
extension HorizontalAlignment: AlignmentDescriptor {
static let alignments = [Self.leading, .center, .trailing]
static func name(of alignment: Self) -> String {
switch alignment {
case .leading:
return "Leading"
case .center:
return "Center"
case .trailing:
return "Trailing"
default:
fatalError("Got some unknown alignment value!!!!")
}
}
}
extension VerticalAlignment: AlignmentDescriptor {
static let alignments = [Self.top, .center, .bottom, .firstTextBaseline, .lastTextBaseline]
static func name(of alignment: Self) -> String {
switch alignment {
case .top:
return "Top"
case .center:
return "Center"
case .bottom:
return "Bottom"
case .firstTextBaseline:
return "FirstTxtBL"
case .lastTextBaseline:
return "LastTxtBL"
default:
fatalError("Got some unknown alignment value!!!!")
}
}
}
struct AlignmentPicker<AD: AlignmentDescriptor>: View {
@Binding var alignment: AD.T
var body: some View {
Picker(selection: Binding<Int>(get: { AD.alignments.firstIndex(of: self.alignment)! }, set: { self.alignment = AD.alignments[$0] }),
label: Text("Choose your alignment")) {
ForEach(0..<AD.alignments.count) { index in
Text(AD.name(of: AD.alignments[index])).tag(index)
}
}.pickerStyle(SegmentedPickerStyle())
}
}
struct ImplicitAlignmentJunk: View {
@State private var alignment: HorizontalAlignment = .trailing
var body: some View {
AlignmentPicker<HorizontalAlignment>(alignment: self.$alignment)
}
}