目录
一、Class(类)
:类支持继承和多态,可以创建一个基类,并定义一些通用的属性和方法,然后创建子类来继承这些属性和方法,并添加或覆盖特定的逻辑。这在构建具有层次结构的复杂应用时非常有用,比如构建自定义的视图控件或组件。
!与struct结构体不同的是,class类中的属性本身不会改变。因此视图不会重新加载以反映该改变以解决此问题。
属性
User
类
User
类继承自 ObservableObject
。这意味着 User
类实例的任何 @Published
属性在值发生变化时都会触发通知。
@Published var firstName = "Bilbo"
: 定义了一个名为firstName
的属性,并初始化为"Bilbo"
。当这个属性的值改变时,任何观察它的视图都会得到通知。@ObservedObject private var user = User()
: 使用@ObservedObject
属性包装器来观察User
类的实例。这意味着ContentView
会监听user
对象中所有@Published
属性的变化,并在这些属性发生变化时自动更新视图。private
关键字表示这个属性只能在ContentView
内部访问。- @Published
-
@Published
是ObservableObject
协议的一部分,用于标记类中的属性,以便当这些属性发生变化时,可以通知任何观察这些属性的对象。在User
类中,firstName
和lastName
属性都被标记为@Published
,这意味着当这些属性的值发生变化时,任何观察User
实例的视图或对象都会收到通知,并有机会更新自己。 -
@ObservedObject
-
@ObservedObject
是一个属性包装器,用于在SwiftUI视图中观察一个遵循ObservableObject
协议的对象。在ContentView
结构体中,user
属性被标记为@ObservedObject
,这意味着ContentView
会观察user
对象的变化。当user
对象中的任何@Published
属性发生变化时,ContentView
将自动重新渲染以反映这些变化。
二、显示视图
表格(视图滑入)
基本:
-》@State private var showingSheet = false
这里定义了一个私有状态变量 showingSheet
,并使用 @State
属性包装器来包裹它。@State
表示这个变量是一个响应式状态,当它的值改变时,与之相关的视图将会自动更新。初始时,showingSheet
的值为 false
,意味着 sheet 视图默认是不显示的。
-》self.showingSheet.toggle()
当按钮被点击时,执行这个闭包内的代码。这里调用了 toggle()
方法来切换 showingSheet
的值。如果 showingSheet
是 false
,则将其设置为 true
,反之亦然。这意味着每次点击按钮时,sheet 的显示状态都会切换。
-》.sheet(isPresented: $showingSheet) {
这里使用了 sheet
修饰符来添加一个 sheet 视图。isPresented
参数控制 sheet 的显示与隐藏,$
符号是 SwiftUI 中用于引用包装器内部值的语法,它表示 showingSheet
的响应式绑定。
-》SecondView()
当 sheet 被显示时,它会展示 SecondView
视图的内容。SecondView
应该是一个遵循 View
协议的结构体或其他视图类型。
进化1.0:
-》self.showingSheet
是一个布尔类型的状态变量(使用 @State
属性包装器定义),toggle()
方法会切换其值。如果 self.showingSheet
原来是 false
(表示 sheet 视图是隐藏的),调用 toggle()
后它会变成 true
,从而触发 sheet 视图的显示。
-》使用 sheet
修饰符将一个 sheet 视图附加到按钮上。isPresented
参数绑定到 showingSheet
的响应式绑定($showingSheet
)上,这意味着当 showingSheet
的值改变时,sheet 视图的显示状态也会相应改变。sheet 视图的内容是 SecondView
视图,并传递了一个字符串参数 "twostraws"
。
进化2.0(应用环境)
@Environment
属性包装器用于从环境中获取值。在这个例子中,它用于获取当前视图的 presentationMode
。presentationMode
是一个包含有关视图如何被呈现的信息的对象,它有一个 dismiss()
方法,可以用于解散视图(即关闭模态视图或 sheet)。
-
self.presentationMode: 这是在
SecondView
中定义的@Environment
属性,它允许我们访问当前视图的呈现模式。呈现模式包含了关于视图如何被呈现的信息,包括它是否是一个模态视图(如 sheet 或 popover),以及是否有方法可以用来解散它。 -
wrappedValue:
presentationMode
是一个EnvironmentObject
类型的属性,而wrappedValue
是这个属性的一个属性,它提供了对实际环境值的访问。在 SwiftUI 中,使用@Environment
属性包装器时,通常需要通过wrappedValue
来访问实际的值。 -
dismiss(): 这是
PresentationMode
类型的一个方法,用于解散当前视图。当这个方法被调用时,如果SecondView
是作为一个模态视图(如 sheet)被呈现的,那么它将被关闭或解散。
@Environment
@Environment
属性包装器用于从当前环境中获取一个值。SwiftUI 的环境是一种机制,它允许在视图层次结构中传递共享数据或功能,而不需要显式地通过每个视图层的属性或参数进行传递。
使用 @Environment
,可以获取如下类型的环境值:
- 呈现模式 (
presentationMode
): 允许你控制视图的呈现(如模态视图或 sheet)以及解散它们。 - 尺寸类别 (
sizeCategory
): 反映当前设备的文本尺寸类别,这在响应式设计中很有用。 - 颜色方案 (
colorScheme
): 提供当前设备使用的颜色方案(如暗模式或亮模式)。 - 布局方向 (
layoutDirection
): 反映当前设备的布局方向(从左到右或从右到左)。 - 动态类型 (
dynamicType
): 允许你访问设备的动态类型设置,这会影响文本的大小和样式。 - 和更多其他环境值。
三、删除
navigationBaritems(leading: EditButton()):
-》navigationBarItems
是 NavigationView
的一个修饰符,它允许在导航栏中添加一个或多个按钮或其他视图。这些视图通常用于提供页面级的操作,如编辑、保存或取消。
leading
是 navigationBarItems
修饰符的一个参数,它指定了视图应该被放置在导航栏的哪个位置。leading
意味着视图将出现在导航栏的左侧(对于从左到右的布局)。
EditButton()
是一个 SwiftUI 提供的函数,它创建了一个标准的编辑按钮。当点击这个按钮时,列表通常会进入编辑模式,显示每个列表项的删除按钮。这使得用户可以轻松地删除列表中的特定项。
func removeRows (at offsets: IndexSet) {
numbers.remove(at0ffsets: offsets):
定义了一个函数 removeRows
,它接受一个参数 offsets
,类型为 IndexSet
。IndexSet
是一个集合类型,用于表示一个或多个非连续的整数索引。在 SwiftUI 的列表编辑上下文中,IndexSet
通常用来表示用户选择要删除的行的索引集合。
函数体
numbers.remove(at: offsets)
在函数体中,调用了 numbers
数组的 remove(at:)
方法,传入 offsets
作为参数。这个方法的目的是从 numbers
数组中移除在 offsets
中指定的索引位置的元素。具体来说,对于 offsets
中的每个索引,numbers
数组中对应位置的元素都将被移除。
四、存储用户数据
1.默认标准
-》使用用户默认启动标准,这是用户默认设置的内置实例,并附加到我们的应用中若,使用的是更高级的应用,还可以创建自己的实例,例如,想要在可能创建的多个应用扩展中共享默认设置自己的用户默认实例,其次是一个单一的设置方法,接受几乎所有数据整数,布尔型字符串,以及其他第三种,在这种情况下,关键是将字符串名称附加到此数据上。像常规的Swift字符串一样,重要的是我们使用相同的键从用户默认值中读取数据。
~读取数据,不是将抽头计数设置为零开始,应该使其像该用户那样从用户默认值中读回值
实例:
>>UserDefaults.standard.integer(forKey: "Tap")
-初始化值。这意味着应用启动时,会从 UserDefaults
中读取之前保存的点击次数。如果 UserDefaults
中没有对应的键 "Tap"
则 tap
会被初始化为 0。
>>UserDefaults.standard.set(self.tapCount, forKey: "Tap")-按钮点击事件处理。
当用户点击按钮时,会执行这个闭包代码。首先,tapCount
的值加 1。然后,新的 tapCount
值被存储到 UserDefaults
中,键为 "TapCount"
。这样,即使应用被关闭再重新打开,点击次数也会被保留下来。
2.JSON
JSON 数据的编码和解码通常使用 Swift 标准库中的 JSONEncoder
和 JSONDecoder
类来完成。这两个类都遵循 Codable
协议,这意味着任何遵循 Codable
协议的类型都可以被编码为 JSON 或从 JSON 解码。
-JSONEncoder:
用于将 Swift 对象转换为 JSON 格式的数据
-JSONDecoder:
用于将 JSON 格式的数据解码为 Swift 对象
——》定义 user 状态变量:@State private var user = User(firstName: "Taylor", lastName: "Swift")定义了一个私有状态变量 user
,它的类型是 User
。User
类应该实现 Codable
协议,以便它可以被 JSONEncoder
编码。状态变量用于在视图中保存和管理数据。
——》初始化 JSON 编码器:let encoder = JSONEncoder(),创建了一个 JSONEncoder
对象,用于将 User
对象转换为 JSON 数据。
——》尝试编码 user 对象:if let data = try? encoder.encode(self.user) ,使用 try?
运算符尝试调用 encode(self.user)
方法,将 self.user
对象编码为 JSON 数据。如果编码成功,data
将包含编码后的数据;如果编码失败,data
将为 nil
。
——》保存编码后的数据到 UserDefaults:UserDefaults.standard.set(data, forKey: "userData")如果编码成功(即 data
不为 nil
),则将编码后的 JSON 数据保存到 UserDefaults
中,键名为 "userData"
。这样,应用可以在后续启动时从这个键中读取数据。
五、项目结构-小费改版
-》定义 ExpenseItem 结构体:
struct ExpenseItem: Identifiable {
let id = UUID()
let name: String
let type: String
let amount: Int
}定义了一个名为 ExpenseItem
的结构体,用于表示一个费用项目。它包含 name
(名称)、type
(类型)和 amount
(金额)属性,并实现了 Identifiable
协议,自动生成一个唯一的 id
属性。
-》定义 Expenses 类:
class Expenses: ObservableObject { @Published var items = [ExpenseItem]() }
定义了一个名为 Expenses
的类,它继承自 ObservableObject
。这个类包含一个 items
数组,用于存储 ExpenseItem
对象,并使用 @Published
修饰符使得这个数组的变化可以被 SwiftUI 视图观察到。
-》添加删除功能:
.onDelete(perform: removeItems)
给列表添加了删除功能,当用户尝试删除列表中的某个项目时,会调用 removeItems
函数。
-》设置导航栏标题和按钮:
.navigationBarTitle("iExpense")
.navigationBarItems(trailing:
Button(action: {
let expense = ExpenseItem(name: "Test", type: "Personal", amount: 5) self.expenses.items.append(expense) }
) { Text("Add")
} )给 NavigationView
设置了标题为 "iExpense",并在导航栏的右侧添加了一个按钮。点击这个按钮会创建一个新的 ExpenseItem
对象,并将其添加到 expenses.items
数组中。
-》定义 removeItems 函数用于处理列表:
func removeItems(at offsets: IndexSet)
{ expenses.items.remove(atOffsets: offsets) }接受一个 IndexSet
类型的参数 offsets
。IndexSet
是一个集合类型,用于表示一系列不连续的索引。在这个上下文中,offsets
表示用户在列表界面上选择并希望删除的项目的索引集合。调用了 expenses.items
数组的 remove(atOffsets:)
方法,用于从数组中移除在 offsets
中指定的索引位置上的元素。换句话说,它删除了用户在列表中选择的所有费用项目。