削除できるリストを作成する
Building a list we can delete from
import SwiftUI
ファイル名;iExpense
struct ContentView: View {
struct ExpenseItem {
let name: String
let type: String
let amount: Int
}
class Expenses: ObservableObject {
@Published var items = [ExpenseItem]()
}
@ObservedObject var expenses = Expenses()
func removeItems(at offsets: IndexSet) {
expenses.items.remove(atOffsets: offsets)
}
var body: some View {
NavigationView {
List {
ForEach(expenses.items, id: \.name) { item in
Text(item.name)
}
.onDelete(perform: removeItems)
}
.navigationBarTitle("iExpense")
.navigationBarItems(trailing:
Button(action: {
let expense = ExpenseItem(name: "Test", type: "Personal", amount: 5)
self.expenses.items.append(expense)
}) {
Image(systemName: "plus")
}
)
}
}
}
SwiftUIWorking with Identifiable items in SwiftUI
識別可能なアイテムを操作する
UUIDは「普遍的に一意の識別子
UUIDは、08B15DB4-2F02-4AB8-A965-67A9C90D8A44のような長い16進文字列です。したがって、これは8桁、4桁、4桁、4桁、12桁の数字であり、3番目のブロックの最初の数字に4があることが唯一の要件です。固定の4を減算すると、31桁になり、それぞれが16の値のいずれかになります。
Identifiable これはSwiftに組み込まれているプロトコルの1つであり、「このタイプは一意に識別できる」ことを意味します。
import SwiftUI
//------------------------------
struct ExpenseItem: Identifiable {
let id = UUID()
let name: String
let type: String
let amount: Int
}
//------------------------------
class Expenses: ObservableObject {
@Published var items = [ExpenseItem]()
}
//------------------------------
struct ContentView: View {
@State private var showingAddExpense = false
@ObservedObject var expenses = Expenses()
func removeItems(at offsets: IndexSet) {
expenses.items.remove(atOffsets: offsets)
}
var body: some View {
NavigationView {
List {
ForEach(expenses.items) { item in
Text(item.name)
}
.onDelete(perform: removeItems)
}
.navigationBarTitle("iExpense")
.navigationBarItems(trailing:
Button(action: {
let expense = ExpenseItem(name: "Test", type: "Personal", amount: 5)
self.expenses.items.append(expense)
}) {
Image(systemName: "plus")
}
)
// .sheet(isPresented: $showingAddExpense) {
// // show an AddView here
// AddView(expenses: self.expenses)
// }
}
}
}
//------------------------------
監視対象オブジェクトを新しいビューと共有する
Sharing an observed object with a new view
準拠するクラスはObservableObject、複数のSwiftUIビューで使用できます。これらのビューはすべて、クラスの公開されたプロパティが変更されると更新されます。
ファイル名;AddView.swift
struct AddView: View {
@ObservedObject var expenses: Expenses
@State private var name = ""
@State private var type = "Personal"
@State private var amount = ""
static let types = ["Business", "Personal"]
var body: some View {
NavigationView {
Form {
TextField("Name", text: $name)
Picker("Type", selection: $type) {
ForEach(Self.types, id: \.self) {
Text($0)
}
}
TextField("Amount", text: $amount)
.keyboardType(.numberPad)
}
.navigationBarTitle("Add new expense")
}
}
}
struct AddView_Previews: PreviewProvider {
static var previews: some View {
AddView(expenses: Expenses())
}
}
//--------------------------------------------------
struct ExpenseItem: Identifiable {
let id = UUID()
let name: String
let type: String
let amount: Int
}
class Expenses: ObservableObject {
@Published var items = [ExpenseItem]()
}
struct ContentView: View {
@State private var showingAddExpense = false
@ObservedObject var expenses = Expenses()
func removeItems(at offsets: IndexSet) {
expenses.items.remove(atOffsets: offsets)
}
var body: some View {
NavigationView {
List {
ForEach(expenses.items) { item in
Text(item.name)
}
.onDelete(perform: removeItems)
}
.navigationBarTitle("iExpense")
.navigationBarItems(trailing:
Button(action: {
self.showingAddExpense = true
}) {
Image(systemName: "plus")
}
)
.sheet(isPresented: $showingAddExpense) {
AddView(expenses: self.expenses)
}
}
}
}
+ボタンをタップAddViewして、さまざまなフィールドに入力できる場所を表示し、スワイプして閉じることができます。
UserDefaultsで変更を永続的にする
Making changes permanent with UserDefaults
次に、presentationMode.wrappedValue.dismiss()ビューにそれ自体を閉じさせたいときに呼び出す必要があります。これにより、showingAddExpensein のブール値がContentViewfalseに戻り、が非表示になりAddViewます。AddView新しい経費項目を作成して既存の経費に追加する[保存]ボタンが既にあるので、次の直後の行にこれを追加します。
isPresentedシートのパラメーターにリンク
self.presentationMode.wrappedValue.dismiss()
struct AddView: View {
@ObservedObject var expenses: Expenses
//追加
@Environment(\.presentationMode) var presentationMode
@State private var name = ""
@State private var type = "Personal"
@State private var amount = ""
static let types = ["Business", "Personal"]
var body: some View {
NavigationView {
Form {
TextField("Name", text: $name)
Picker("Type", selection: $type) {
ForEach(Self.types, id: \.self) {
Text($0)
}
}
TextField("Amount", text: $amount)
.keyboardType(.numberPad)
}
.navigationBarTitle("Add new expense")
.navigationBarItems(trailing: Button("Save") {
if let actualAmount = Int(self.amount) {
let item = ExpenseItem(name: self.name, type: self.type, amount: actualAmount)
self.expenses.items.append(item)
}
//追加 isPresentedシートのパラメーターにリンク
self.presentationMode.wrappedValue.dismiss()
})
}
}
}
struct AddView_Previews: PreviewProvider {
static var previews: some View {
AddView(expenses: Expenses())
}
}
//--------------------------------------------------
import SwiftUI
//---------------------------------------
struct ExpenseItem: Identifiable, Codable {
let id = UUID()
let name: String
let type: String
let amount: Int
}
//---------------------------------------
class Expenses: ObservableObject {
//@Published var items = [ExpenseItem]()
@Published var items: [ExpenseItem] {
didSet {
let encoder = JSONEncoder()
if let encoded = try? encoder.encode(items) {
UserDefaults.standard.set(encoded, forKey: "Items")
}
}
}
//---------------
//カスタム初期化子を実装
init() {
if let items = UserDefaults.standard.data(forKey: "Items") {
let decoder = JSONDecoder()
if let decoded = try? decoder.decode([ExpenseItem].self, from: items) {
self.items = decoded
return
}
}
self.items = []
}
}
//---------------------------------------
struct ContentView: View {
@State private var showingAddExpense = false
@ObservedObject var expenses = Expenses()
func removeItems(at offsets: IndexSet) {
expenses.items.remove(atOffsets: offsets)
}
var body: some View {
NavigationView {
List {
ForEach(expenses.items) { item in
HStack {
VStack(alignment: .leading) {
Text(item.name)
.font(.headline)
Text(item.type)
}
Spacer()
Text("$\(item.amount)")
}
}
.onDelete(perform: removeItems)
}
.navigationBarTitle("iExpense")
.navigationBarItems(trailing:
Button(action: {
self.showingAddExpense = true
}) {
Image(systemName: "plus")
}
)
.sheet(isPresented: $showingAddExpense) {
AddView(expenses: self.expenses)
}
}
}
}