In the answers to my question on How to add a generic SwiftUI view to another view, I learned that this can be done using @ViewBuilder
.
While this works fine for most of my use cases, I now came across a new problem:
- The
@ViewBuilder
solution basically creates theContentView
view outside theGenericView<Content: View>
- The
ContentView
is than passed to theGenericView<Content: View>
which shows it
BUT: What if the ContentView
has to be created inside GenericView<Content: View>
because it requires some parameters which are only available there?
Example:
UserView
is created by providing a user IDUserView
s view model fetches the user name using the ID. So the which creates theUserView
does only know the ID but not the name. The name is only available withinUserView
UserView
is used at different places within an app or even in different apps. The different places require to show the username in different layouts/styles/etc. To not hard code all layouts intoUserView
, the view is generic and is given aContent
view type which is used to show the username
Code
protocol NameView: View {
init(name: String)
}
struct NameOnlyView: NameView {
private let name: String
init(name: String) {
self.name = name
}
var body: some View {
Text(name)
}
}
struct NameGreetingView: NameView {
private let name: String
init(name: String) {
self.name = name
}
var body: some View {
Text("Hello \(name)")
}
}
struct UserView<Content: NameView>: View {
private let name: String
private let nameView: Content
init(userId: Int, @ViewBuilder nameViewBuilder: (String) -> Content) {
name = LoadUserName(usingId: userId)
nameView = nameViewBuilder(name)
}
var body: some View {
nameView
}
}
struct SomeView: View {
var body: some View {
// What I would like to do
UserView(userId: 123, NameOnlyView)
UserView(userId: 987, NameGreetingView)
// What is required instead
UserView(userId: 123) {
NameOnlyView("Name which is not known here")
}
}
}
Of course I could move the logic to load the username from the given ID and make it available in SomeView
. However, this is just an example for any value which is only available in UserView
but not in SomeView
. Especially when using the UserView
in different apps I do not want to implement the same logic to load the username (or whatever) in all possible parent views of UserView
.
Can this be solved using the @ViewBuilder
solution?
Can this be solved in SwiftUI at all?
Or am I completely on the wrong track?