SwiftUI(3)

目录

一、Class(类)

属性

User 类

二、显示视图

表格(视图滑入)

基本:

进化1.0:

进化2.0(应用环境)

@Environment

三、删除

函数体

四、存储用户数据

1.默认标准

2.JSON

-JSONEncoder:

-JSONDecoder:

五、项目结构-小费改版


一、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 属性包装器用于从环境中获取值。在这个例子中,它用于获取当前视图的 presentationModepresentationMode 是一个包含有关视图如何被呈现的信息的对象,它有一个 dismiss() 方法,可以用于解散视图(即关闭模态视图或 sheet)。

  • self.presentationMode: 这是在 SecondView 中定义的 @Environment 属性,它允许我们访问当前视图的呈现模式。呈现模式包含了关于视图如何被呈现的信息,包括它是否是一个模态视图(如 sheet 或 popover),以及是否有方法可以用来解散它。

  • wrappedValuepresentationMode 是一个 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,类型为 IndexSetIndexSet 是一个集合类型,用于表示一个或多个非连续的整数索引。在 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,它的类型是 UserUser 类应该实现 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 类型的参数 offsetsIndexSet 是一个集合类型,用于表示一系列不连续的索引。在这个上下文中,offsets 表示用户在列表界面上选择并希望删除的项目的索引集合。调用了 expenses.items 数组的 remove(atOffsets:) 方法,用于从数组中移除在 offsets 中指定的索引位置上的元素。换句话说,它删除了用户在列表中选择的所有费用项目。

  • 21
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值