Section 11/181 menit

11. Integrasi dengan SwiftUI

11. Integrasi dengan SwiftUI

.modelContainer Modifier

swift
@main
struct BookApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
        .modelContainer(for: [Book.self, Author.self, Tag.self])
        // SwiftData otomatis membuat container dengan konfigurasi default
    }
}

@Environment(.modelContext)

Di SwiftUI view, akses context untuk operasi insert/delete:

swift
struct AddBookView: View {
    @Environment(\.modelContext) private var context
    @Environment(\.dismiss) private var dismiss

    @State private var title = ""
    @State private var author = ""
    @State private var year = Calendar.current.component(.year, from: Date())

    var body: some View {
        NavigationStack {
            Form {
                TextField("Judul Buku", text: $title)
                TextField("Penulis", text: $author)
                Stepper("Tahun: \(year)", value: $year, in: 1900...2100)
            }
            .navigationTitle("Tambah Buku")
            .toolbar {
                ToolbarItem(placement: .cancellationAction) {
                    Button("Batal") { dismiss() }
                }
                ToolbarItem(placement: .confirmationAction) {
                    Button("Simpan") {
                        let book = Book(title: title, author: author, publishedYear: year)
                        context.insert(book)
                        dismiss()
                    }
                    .disabled(title.isEmpty || author.isEmpty)
                }
            }
        }
    }
}

@Bindable untuk Edit In-Place

@Bindable memungkinkan dua-arah binding langsung ke @Model property:

swift
struct EditBookView: View {
    @Bindable var book: Book  // gunakan @Bindable, bukan @State atau @ObservedObject
    @Environment(\.modelContext) private var context

    var body: some View {
        Form {
            TextField("Judul", text: $book.title)          // binding langsung ke model
            TextField("Penulis", text: $book.author)
            Toggle("Sudah Dibaca", isOn: $book.isRead)
            DatePicker(
                "Tanggal Ditambahkan",
                selection: $book.addedAt,
                displayedComponents: .date
            )
        }
        .navigationTitle("Edit Buku")
        .onChange(of: book.title) { _, _ in
            try? context.save()  // autosave saat berubah
        }
    }
}

Preview dengan ModelContainer In-Memory

swift
#Preview {
    let config = ModelConfiguration(isStoredInMemoryOnly: true)
    let container = try! ModelContainer(for: Book.self, configurations: config)

    // Isi sample data
    let context = container.mainContext
    context.insert(Book(title: "Clean Code", author: "Robert C. Martin", publishedYear: 2008))
    context.insert(Book(title: "The Pragmatic Programmer", author: "Hunt & Thomas", publishedYear: 1999))

    return BookListView()
        .modelContainer(container)
}