SwiftUI:如何获取ViewBuilder传入子视图的索引与Identifiable ID?
SwiftUI自定义PagingView:如何获取ViewBuilder子视图的索引与ID映射?
需求概述
我要实现一个类似SwiftUI List的PagingView组件,核心要求有两个:
- 可接收任意一组视图作为内容
- 支持基于
Identifiable协议的项目选择(以UUID作为标识)
父组件的使用示例如下:
struct MainView: View { private let list: [UUID] = [...] @State private var selection: UUID? var body: some View { PagingView($selection) { ForEach(list) { RowItemView(model: $0) } } } }
当前PagingView的基础实现
目前的PagingView仅接收选择状态绑定和内容视图,代码结构如下:
struct PagingView<Content>: View where Content: View { private let content: Content @Binding private var selection: UUID? init(_ selection: Binding<UUID?>, @ViewBuilder content: @escaping () -> Content) { [...] } var body: some View { HStack { content } } }
核心痛点
现在需要在PagingView内部根据子视图的整数索引计算偏移位置,但选择状态传递的是UUID类型的ID,因此必须建立子视图索引与对应ID的映射关系。当前的核心问题是:如何获取ViewBuilder闭包提供的子视图的索引和ID信息?
已尝试的方案及局限
将Content改为数组类型
修改后要求内容闭包返回[Content],通过enumerated()遍历获取索引,但这种方式会强制父组件必须直接返回视图数组,无法正常使用ForEach等SwiftUI原生视图构造器,适用范围极窄:struct PagingView<Content>: View where Content: View { private let content: [Content] @Binding private var selection: UUID? init(_ selection: Binding<UUID?>, @ViewBuilder content: @escaping () -> [Content]) { [...] } var body: some View { HStack { ForEach(content.enumerated()) { index, item in // 尝试保存索引与ID的映射 store(item.id, for: index) return item } } } }同步索引与选择状态的双绑定
添加额外的@Binding变量跟踪选中索引,通过onChange同步索引和UUID选择值,但这种方式需要在父组件维护额外状态,且同步逻辑容易出现不一致,不是最优解。
以上两种方案都没能彻底解决问题,求可行的实现思路。
内容的提问来源于stack exchange,提问作者Dzeremix
相关产品推荐
相关产品推荐

