SwiftUI中如何在多视图间共享自定义类型数组?
解决SwiftUI多视图共享相机数组的问题
问题原因
你之前的代码里,ContentView和AddCameraView各自定义了独立的@State var cameraArray,两个数组完全无关,所以在弹窗里添加的相机不会同步到首页列表。要实现多视图共享数据,需要用ObservableObject来统一管理数据源。
解决方案步骤
- 创建一个
ObservableObject类型的视图模型(ViewModel),用来管理相机数组,数组用@Published标记,这样数据变化时会自动通知所有关联视图更新。 - 在首页视图用
@StateObject持有这个ViewModel(确保整个App生命周期内只有一个实例)。 - 把ViewModel实例传递给弹窗视图,弹窗用
@ObservedObject接收,从而共享同一数据源。 - 修改弹窗的保存逻辑,直接操作ViewModel里的数组,而不是本地数组。
修改后的完整代码
1. 相机视图模型(CameraViewModel.swift)
import Foundation import SwiftUI class CameraViewModel: ObservableObject { // @Published标记的数组,变化时自动通知视图更新 @Published var cameraArray = [CameraStruct]() // 封装添加相机的方法,逻辑更清晰 func addCamera(manufacturer: String, model: String) { let newCamera = CameraStruct(id: UUID(), camManufacturer: manufacturer, camModel: model) cameraArray.insert(newCamera, at: 0) } }
2. 首页列表视图(ContentView.swift)
import SwiftUI struct ContentView: View { @State private var showingSheet = false // 用@StateObject持有ViewModel,保证全局唯一实例 @StateObject private var viewModel = CameraViewModel() var body: some View { // iOS16+推荐用NavigationStack替代NavigationView NavigationStack { List(viewModel.cameraArray) { camera in Text("\(camera.camManufacturer) \(camera.camModel)") } } .navigationTitle("Cameras") .toolbar { Button { showingSheet.toggle() } label: { Label("Add Camera", systemImage: "plus") } } // 弹窗视图接收ViewModel实例 .sheet(isPresented: $showingSheet) { AddCameraView(viewModel: viewModel) } } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() } }
3. 弹窗添加视图(AddCameraView.swift)
import SwiftUI struct AddCameraView: View { @Environment(\.dismiss) var dismiss // 接收首页传递的ViewModel,共享数据源 @ObservedObject var viewModel: CameraViewModel @State private var camManufacturerInput = "" @State private var camModelInput = "" var body: some View { NavigationStack { Form { Section(header: Text("General Info")) { TextField("Camera Manufacturer", text: $camManufacturerInput) TextField("Camera Model", text: $camModelInput) } } .navigationTitle("Add Camera Details") .toolbar { ToolbarItemGroup(placement: .navigationBarTrailing) { Button("Save") { // 调用ViewModel的方法添加相机 viewModel.addCamera(manufacturer: camManufacturerInput, model: camModelInput) dismiss() } // 保持输入验证逻辑 .disabled(camManufacturerInput.isEmpty || camModelInput.isEmpty) } } } } } struct AddCameraView_Previews: PreviewProvider { static var previews: some View { // 预览时传入ViewModel实例 AddCameraView(viewModel: CameraViewModel()) } }
4. 相机结构体(CameraStruct.swift)
import Foundation struct CameraStruct: Identifiable, Codable { var id: UUID var camManufacturer: String var camModel: String }
关键说明
@StateObject:用于在父视图中创建并持有ObservableObject实例,确保实例在视图生命周期内稳定存在。@ObservedObject:用于在子视图中接收ObservableObject实例,监听其数据变化。@Published:标记ObservableObject中的属性,当属性值变化时自动发送通知,触发视图更新。
内容的提问来源于stack exchange,提问作者miothethis
相关产品推荐
相关产品推荐

