You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI中如何在多视图间共享自定义类型数组?

解决SwiftUI多视图共享相机数组的问题

问题原因

你之前的代码里,ContentView和AddCameraView各自定义了独立的@State var cameraArray,两个数组完全无关,所以在弹窗里添加的相机不会同步到首页列表。要实现多视图共享数据,需要用ObservableObject来统一管理数据源。

解决方案步骤

  1. 创建一个ObservableObject类型的视图模型(ViewModel),用来管理相机数组,数组用@Published标记,这样数据变化时会自动通知所有关联视图更新。
  2. 在首页视图用@StateObject持有这个ViewModel(确保整个App生命周期内只有一个实例)。
  3. 把ViewModel实例传递给弹窗视图,弹窗用@ObservedObject接收,从而共享同一数据源。
  4. 修改弹窗的保存逻辑,直接操作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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 03:45:05