Open aheze opened 1 year ago
If I understood correctly and you need any item conforming to Setting to basically act as a View then maybe you could do
public protocol Setting: View, Identifiable { /// Hashable can be used instead, just add hash function to below extension
/// Random required parameters
var id: String { get }
var title: String { get }
var icon: Image { get }
}
/// To identify the View
public extension Setting {
var id: String {
/// Some string id
}
}
Then declare and create the views with
struct SomeSettingItem: Setting {
var title: String
var icon: Image
var body: some View {
Button(action: {
/// Do something
}) {
HStack {
icon
.resizable()
.frame(width: 20, height: 20)
.foregroundColor(.red)
Text(title)
.font(.body)
.foregroundColor(.red)
}
}
}
}
SomeSettingItem(title: "Item 1", icon: Image(systemName: "house"))
And then declaring some view to hold these generic elements would possibly be
public struct SettingView<T>: View where T: Setting
And for example then render them easily in a ForEach as views
ForEach(items, id: \.id) { item in
item
}
The problem
Currently SettingView renders each element via a huge
switch
.This has several limitations:
No support for custom
Setting
sThe switch statement checks against
SettingText
,SettingButton
,SettingToggle
, etc. Say we had our own element calledSettingLabel
:This would fall through in the switch statement and error out.
Limited customization (no subclass / composing support)
This is related to the above issue. Let's say you want to make a bunch of
SettingText
s blue. Right now you need to do this:Ideally you'd be able to make a new element that conforms from
Setting
.This code compiles, but it will fall through in the above mentioned issue with the switch statement.
Reliance on stable
ID
identifiersYou might have noticed all the
var id: AnyHashable?
s floating around. This is because of theForEach
loop forSettingPage
,SettingGroup
, andSettingTupleView
.Currently,
Setting
synthesizes this ID depending on the element — forSettingText
, it gets thetitle
property. ForSettingTupleView
, it getstuple.flattened.compactMap { $0.textIdentifier }.joined()
.https://github.com/aheze/Setting/blob/main/Sources/Setting.swift#L18-L38
Ideally, we could get rid of this
ID
and just use aView
's default identity. (For more details, see How the SwiftUI View Lifecycle and Identity work, "Identity of a view" section.)No support for custom view modifiers
This requires changes to
SettingBuilder
.The solution
SettingView
needs to be generic, resembling SwiftUI'sView
as closely as possible.If possible, we should make
Setting
conform toView
, so that we can render it directly without the need for a hugeswitch
.I've attempted this and got lost quickly — I'm not good with generics.
Any help? :)