在回答我关于如何将通用SwiftUI视图添加到另一个视图的问题时,我了解到这可以使用@ViewBuilder
来完成。
虽然这对我的大多数用例来说都很好,但我现在遇到了一个新问题:
@ViewBuilder
解决方案基本上在GenericView<Content: View>
外部创建ContentView
视图- 然后将
ContentView
传递给显示它的GenericView<Content: View>
但是:如果必须在GenericView<Content: View>
内部创建ContentView
,因为它需要一些仅在那里可用的参数,该怎么办?
示例:
UserView
是通过提供用户ID创建的UserView
的视图模型使用ID获取用户名。因此创建UserView
的用户只知道ID而不知道名称。该名称仅在UserView
中可用UserView
在应用程序内的不同位置使用,甚至在不同的应用程序中使用。不同的地方需要以不同的布局/样式等显示用户名。为了不将所有布局硬编码为UserView
,视图是通用的,并被赋予用于显示用户名的Content
视图类型
编码
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")
}
}
}
当然,我可以移动逻辑,从给定的ID加载用户名,并使其在SomeView
中可用。然而,这只是仅在UserView
中可用但在SomeView
中不可用的任何值的示例。特别是当在不同的应用程序中使用UserView
时,我不想在UserView
的所有可能的父视图中实现相同的逻辑来加载用户名(或其他(。
是否可以使用@ViewBuilder
解决方案解决此问题
这能在SwiftUI中解决吗
还是我完全走错了路
看看SwiftUI的样式系统,例如ButtonStyle,博客文章Encapsulating SwiftUI视图样式(Swift by Sundell(有一些很棒的信息。希望你最终能得到这样的东西:
List {
UserView(userId: 987)
UserView(userId: 123)
}
.userViewStyle(.nameOnly)