昨天介紹了 ModelContainer 今天繼續來實作 SwiftData 吧。
實際操作之前,這裡參考網路上的資料完成 UI 的部分,中間還有使用到一些新的 View 跟 modifier,不過這裡的 UI 功能很簡單,就只是新增資料跟顯示資料而已,還沒完全跟 SwiftData 做連接。
import SwiftUI
import SwiftData
struct ContentView: View {
@State private var isShowItemSheet = false
var expenses: [Expense] = []
var body: some View {
NavigationStack {
List {
ForEach(expenses) { expense in
ExpenseCell(expense: expense)
}
}
.navigationTitle("Expenses")
.navigationBarTitleDisplayMode(.large)
.sheet(isPresented: $isShowItemSheet) {
AddExpenseSheet()
}
.toolbar {
if !expenses.isEmpty {
Button("Add Expense", systemImage: "plus") {
isShowItemSheet = true
}
}
}
.overlay {
if expenses.isEmpty {
ContentUnavailableView {
Label("No Expense", systemImage: "list.bullet.rectangle.portrait")
} description: {
Text("Start adding expense to see your list.")
} actions: {
Button("Add Expense") {
isShowItemSheet = true
}
}
.offset(y: -60)
}
}
}
}
}
#Preview {
ContentView()
}
struct ExpenseCell: View {
let expense: Expense
var body: some View {
HStack {
Text (expense.date, format: .dateTime.month(.abbreviated).day())
.frame(width: 70, alignment: .leading)
Text (expense.name)
Spacer()
Text (expense.value, format: .currency(code: "USD"))
}
}
}
struct AddExpenseSheet: View {
@Environment(\.dismiss) private var dismiss
@State private var name: String = ""
@State private var date: Date = .now
@State private var value: Double = 0
var body: some View {
NavigationStack {
Form {
TextField("Expense name", text: $name)
DatePicker("Date", selection: $date, displayedComponents: .date)
TextField("value", value: $value, format: .currency(code: "USD"))
.keyboardType(.decimalPad)
}
.navigationTitle("New Expense")
.navigationBarTitleDisplayMode(.large)
.toolbar {
ToolbarItemGroup(placement: .topBarLeading) {
Button("Cancel") {
dismiss()
}
}
ToolbarItemGroup(placement: .topBarTrailing) {
Button("Save") {
// Save code
}
}
}
}
}
}
那今天先做到這裡,明天來試試操作吧。