如何用SwiftUI @ViewBuilder创建依赖内部参数的视图?
泛型SwiftUI视图内部创建ContentView的问题
之前我了解到可以用@ViewBuilder实现向泛型SwiftUI视图添加内容,但现在遇到了新的场景限制:
@ViewBuilder方案的本质是在GenericView<Content: View>外部创建ContentView- 再将创建好的
ContentView传入GenericView<Content: View>中展示
但问题在于:如果ContentView必须在GenericView<Content: View>内部创建(因为它需要一些仅该视图内部才有的参数),该怎么处理?
示例场景
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 { // 我期望的写法 UserView(userId: 123, NameOnlyView) UserView(userId: 987, NameGreetingView) // 当前必须写的冗余写法 UserView(userId: 123) { NameOnlyView("这里根本不知道具体名字") } } }
当然,我可以把根据ID加载用户名的逻辑移到SomeView里,但这只是示例,实际场景中可能存在任何仅UserView内部可用、父视图无法获取的值。尤其是在跨应用复用UserView时,我不想在所有可能的父视图中重复实现相同的加载逻辑。
我有几个疑问:
- 能不能用
@ViewBuilder方案解决这个问题? - SwiftUI本身有没有办法处理这种场景?
- 是不是我的整体思路就错了?
内容的提问来源于stack exchange,提问作者Andrei Herford
相关产品推荐
相关产品推荐

