SwiftUI中如何复用同一个列表视图适配多数据源并返回选中数据到对应父视图
SwiftUI 通用复用列表选择视图改造方案
核心改造思路
- 把原来固定绑定CompanyData的视图改为泛型视图,支持任意遵守
Identifiable协议的数据类型传入 - 移除固定的
companyName绑定,改为通用选中回调,直接返回选中的完整模型数据 - 支持自定义列表行视图、自定义导航栏标题,适配不同业务场景的展示需求
- 兼容原有业务逻辑,无需修改现有数据结构即可直接适配使用
改造后完整代码
import SwiftUI import Combine // 泛型通用选择列表视图,支持任意遵守Identifiable的数据类型 struct CommonSelectionView<T: Identifiable, Content: View>: View { @Environment(\.presentationMode) var presentationMode // 外部传入的数据源 let dataList: [T] // 外部传入的导航栏标题 let navTitle: String // 外部自定义列表行的构建闭包 let rowContent: (T) -> Content // 选中条目后的回调,直接返回选中的完整模型数据 let onSelect: (T) -> Void var body: some View { List(dataList) { data in Button(action: { onSelect(data) presentationMode.wrappedValue.dismiss() }) { rowContent(data) } } .navigationBarTitle(navTitle) } } // 预览示例 struct CommonSelectionView_Previews: PreviewProvider { // 模拟测试数据结构 struct TestItem: Identifiable { let id = UUID() let name: String } static var previews: some View { NavigationStack { CommonSelectionView( dataList: [TestItem(name: "测试公司1"), TestItem(name: "测试公司2")], navTitle: "测试选择" ) { item in Text(item.name) } onSelect: { selectedItem in print("选中了\(selectedItem.name)") } } } }
提示:如果需要适配iOS15及以下版本,将调用处的
NavigationStack替换为NavigationView即可。
使用示例
1. 原有公司选择场景适配
// 父视图调用示例 struct CompanySelectParentView: View { @State private var showCompanySelector = false @State private var selectedCompanyName = "" // 你的公司数据源,可根据业务替换 let companyData = [CompanyData]() var body: some View { VStack { Text("已选公司:\(selectedCompanyName)") Button("选择公司") { showCompanySelector = true } } .sheet(isPresented: $showCompanySelector) { NavigationStack { // 传入对应参数即可复用通用选择视图 CommonSelectionView( dataList: companyData, navTitle: "Companies" ) { company in Text(company.name ?? "") } onSelect: { selectedCompany in selectedCompanyName = selectedCompany.name ?? "" } } } } }
2. 其他数据类型使用示例(比如用户选择)
// 任意业务数据结构只要遵守Identifiable协议即可使用 struct User: Identifiable { let id = UUID() let userName: String let phone: String } // 父视图调用 struct UserSelectParentView: View { @State private var showUserSelector = false @State private var selectedUser: User? let userList = [ User(userName: "张三", phone: "13xxxxxxxxx"), User(userName: "李四", phone: "13xxxxxxxxx") ] var body: some View { VStack { Text("已选用户:\(selectedUser?.userName ?? "未选择")") Button("选择联系人") { showUserSelector = true } } .sheet(isPresented: $showUserSelector) { NavigationStack { CommonSelectionView( dataList: userList, navTitle: "选择联系人" ) { user in // 可完全自定义行视图样式 VStack(alignment: .leading) { Text(user.userName) Text(user.phone) .font(.caption) .foregroundColor(.gray) } } onSelect: { selected in selectedUser = selected } } } } }
内容的提问来源于stack exchange,提问作者venkat
相关产品推荐
相关产品推荐

