Search code examples
swiftswiftuiswiftdata

How to pass array of SwiftData models to another view?


I have a simple SwiftData query which stores an array of projects. I want to pass this array to a custom view called: "ProjectView" but I get an error that it doesn't find $projects in scope. If I can only use the query as read only, what even is the purpose of SwiftData? Here is my code:

import SwiftUI
import SwiftData

struct FileModel: Identifiable, Codable, Equatable {
    var id = UUID()
    
    var fileName: String
    var tempName: String = ""
    
    var persistent = false
    
    var data: Data?
    
    var subFiles: [FileModel] = []
    
    var isDirectory: Bool {
        return data == nil || subFiles.isEmpty == false
    }
    
    var isExpanded = true
    var isRenaming = false
    var isDeleting = false
}

@Model class Project {
    var id = UUID()
    var name: String = ""
    var created: String = ""
    var lastModified: String = ""
    
    var files: [FileModel] = []
    
    init() {
        self.name = "New Project"
        self.created = Date.now.formatted(date: .numeric, time: .shortened)
        self.lastModified = created
        self.files = [
            FileModel(fileName: "root", persistent: true)
        ]
    }
}

struct ProjectView: View {
    @Binding var projects: [Project]

    var body: some View {
        ScrollView {
            VStack {
                ForEach($projects) { $project in
                    TextField("Project Name", text: $project.name)
                        .padding()
                        .textFieldStyle(RoundedBorderTextFieldStyle())
                }
            }
            .padding()
        }
    }
}

struct ContentView: View {
    
    @Query var projects: [Project]
    @Environment(\.modelContext) var modelContext
    
    @State private var selectedProjectID: UUID?
    
    var body: some View {
        VStack {
            Text("Hello, world!")
            
            ProjectView(projects: $projects)
                .padding()
        }
        .padding()
    }
}

#Preview(windowStyle: .automatic) {
    ContentView()
}

Would it be possible to somehow pass the projects as an environment values of sth. I am very very new to SwiftData, and already ran into an error I can't fix. Thanks in advance!


Solution

  • @Binding is for value types, for @Model you need @Bindable for each model so change

    @Binding var projects: [Project]
    

    To

    let projects: [Project]
    

    And adjust the ForEach to

    ForEach(projects) { project in
        @Bindable var project = project