【Swift】第八周 iExpense

本文深入探讨了Swift编程中的结构体与类的区别,包括成员方法对成员属性的修改、值拷贝与引用拷贝。接着,讲解了`@State`和`@ObservedObject`在实时更新视图中的作用。此外,还介绍了sheet多视图跳转的实现,从List中删除列表项的方法,以及使用UserDefaults保存用户全局数据。最后,详细讨论了iExpense应用的功能设计与开发,涵盖了界面设计、数据结构和功能实现等方面。
摘要由CSDN通过智能技术生成

1. 结构体和类

1.1 成员方法对成员属性的修改

在这里插入图片描述
以上会出现报错,是因为 struct 属于值类型,默认情况下,它的属性不可以被成员方法修改。

但是以下两种解决方案可以实现修改:

  • 方法一: @State 修饰成员变量
struct ContentView: View {
   

	@State private var myValue = 10
		var body: some View {
   
		Text("Hello, World!")
	}
	
	func canIChangeTheValue(){
   
		self.myValue = 20
	}
}
  • 方法二:使用 修饰成员方法
struct ContentView: View {
   
	private var myValue = 10
	
	var body: some View {
   
		Text("Hello, World!")
	}
	
	mutating func canIChangeTheValue(){
   
		self.myValue = 20
	}
}

在这里插入图片描述
在 class类中,成员方法默认是可以修改成员变量的。

1.2 值拷贝与引用拷贝

struct 类型直接的直接 “=” 赋值,其实是对值进行了一份拷贝,实际的两个值是两个独立的值

struct Resolution {
   
	var width = 0
	var height = 0
}

let hd = Resolution(width: 1920, height: 1080)
var cinema = hd
cinema.width = 2048

print("cinema is now \(cinema.width) pixels wide")
// Prints "cinema is now 2048 pixels wide"

print("hd is still \(hd.width) pixels wide")
// Prints "hd is still 1920 pixels wide"

在这里插入图片描述

class 类之间的 “=” 赋值,是引用赋值,其实是将一个对数据单元的引用地址赋值给另一个类。

注.class 类中的成员变量必须要有初始值或者可选变量

class VideoMode {
   
	var resolution = Resolution()
	var interlaced = false
	var frameRate = 0.0
	var name: String?
}

	let tenEighty = VideoMode()
	tenEighty.resolution = hd
	tenEighty.interlaced = true
	tenEighty.name = "1080i"
	tenEighty.frameRate = 25.0
	
	let alsoTenEighty = tenEighty
	
	alsoTenEighty.frameRate = 30.0

在这里插入图片描述

附:在Java语言中也是同样的道理,根据输出的对象的引用地址相同可以看出,使用"="的赋值,只是拷贝了引用地址。
在这里插入图片描述

2. @State 和 @ObservedObject

2.1 使用@State修饰结构体属性

@State 是对结构体属性的修饰,当结构体 View 中定义的属性被 @State 修饰后,我们就可以在视图上实时监测到这个属性值的变化 并且对视图刷新。

struct User{
   
	var firstName = "Bilbo"
	var lastName = "Baggins"
}

struct ContentView: View {
   

	@State private var user = User()
	
	var body: some View {
   
		VStack{
   
			Text("Your name is: \(user.firstName) \(user.lastName)")
			TextField("First name", text: $user.firstName)
			TextField("Last name", text: $user.lastName)
		}
	}
}

上面代码执行后可以看到在文本框中无论是修改“Firstname”还是“Lastname"那么在Text中都会发生改变。这时因为每当对结构体User的属性改变都相当于重新复制了-份儿结构体的实例,也就是说不管是修改了user.firstName还是user.lastName,这个user就不再是之前的user了,而是一个新的user。而user的改变也就直接导致ContentView的属性改变,所以ContentView也被重新实例化了,于是我们会看到整个视图的内容也发生了变化。其实我们看到的这个变化的视图已经不再是之前的那个视图了。
在这里插入图片描述

如果我们把上述代码的第1行的关键字struct修改为class 后:

class User{
   
	var firstName = "Bilbo"
	var lastName = "Baggins"
}

struct ContentView: View {
   

	@State private var user = User()

	var body: some View {
   
		VStack{
   
			
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_popo_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值