结构体
声明结构体的关键字是struct,使用起来和类相似,但类的成员是引用类型,而结构体的成员是值类型。
值类型在传递和赋值的时候,是进行复制的,那也就是说在修改一处复制体的时候,原来被复制的对象是不受影响的。
引用类型在传递和赋值的时候,是传递引用对象的一个“指向”,所以当对该引用进行修改的时候,是直接直接修改到最原始的对象,即,一旦修改值,则对该原始对象的所有引用都会被同步修改。
在内存中,引用类型的变量是在堆上存储和操作的。值类型的变量是在栈上存储和操作的。两者相比起来,在堆上的变量操作会比较复杂和耗时。所以苹果官方推荐使用结构体,这样可以提高App的运行效率。
结构体的优势:
- 结构较小,适用于复制,相比一个class的实例被多次引用,struct结构体更加安全。
- 无须担心内存泄漏或者多线程冲突安全。
struct student {
var name = "name"
var index = 202100
var height = 160.00
var profession = "profession"
var sex = "男"
}
var xiaoMing = student()
xiaoMing.name = "xiaoMing"
xiaoMing.index = 202101
xiaoMing.height = 172.5
xiaoMing.profession = "计算机科学与技术"
xiaoMing.sex = "男"
print("\(xiaoMing)")
运行结果:
student(name: "xiaoMing", index: 202101, height: 172.5, profession: "计算机科学与技术", sex: "男")
当然也可以在定义结构体的时候不给出初始值,而是给出数据的基本类型。
struct student {
var name : String
var index :Int
var height :CGFloat
var profession : String
var sex : String
}
因为swift中函数也是一种类型,所以结构体中也可以定义函数。
结构体可以有构造方法
struct Student{
//可用结构体名称直接调用属性,不需要创建实例
static let schoolName = "XXX SCHOOL"
var age:Int
var name:String
var score:Float
var isPass:Bool
init(name:String,age:Int,score:Float){
self.name = name
self.age = age
self.score = score
self.isPass = score < 60 ? false : true
}
}
var xiaoMing = Student(name: "xiaoMing", age: 18, score: 100)
var xiaoHong = Student(name: "xiaoHong", age: 16, score: 59)
print(xiaoMing)
xiaoHong.age = 18
print(xiaoHong)
print(Student.schoolName)
运行结果:
Student(age: 18, name: "xiaoMing", score: 100.0, isPass: true)
Student(age: 18, name: "xiaoHong", score: 59.0, isPass: false)
XXX SCHOOL
属性观察
struct Student{
//可用结构体名称直接调用属性,不需要创建实例
static let schoolName = "XXX SCHOOL"
var age:Int
var name:String
var score:Float = 0{
//观察者模式 willSet and didSet
didSet{
isPass = score < 60 ? false : true
}
}
var isPass:Bool = false{
//观察者模式 willSet and didSet
didSet{
self.notication = isPass ? "毋需补考":"请周一进行补考"
}
}
var notication:String = ""
init(name:String,age:Int){
self.name = name
self.age = age
}
}
var xiaoMing = Student(name: "xiaoMing", age: 18)
var xiaoHong = Student(name: "xiaoHong", age: 16)
print(xiaoMing)
print(xiaoHong)
xiaoMing.score = 98
xiaoHong.score = 52
print(xiaoMing)
print(xiaoHong)
运行结果:
Student(age: 18, name: "xiaoMing", score: 0.0, isPass: false, notication: "")
Student(age: 16, name: "xiaoHong", score: 0.0, isPass: false, notication: "")
Student(age: 18, name: "xiaoMing", score: 98.0, isPass: true, notication: "毋需补考")
Student(age: 16, name: "xiaoHong", score: 52.0, isPass: false, notication: "请周一进行补考")
下标语法subscript
struct Student{
var age:Int
var name:String
var classScore:Dictionary<String,Int> = ["chinese":0]
init(name:String,age:Int){
self.name = name
self.age = age
}
subscript(index:String)->Int{
set{
classScore[index] = newValue
}
get{
return classScore[index] ?? 0
}
}
}
var xiaoMing = Student(name: "xiaoMing", age: 18)
var xiaoHong = Student(name: "xiaoHong", age: 16)
print(xiaoMing)
print(xiaoHong)
xiaoMing["chinese"] = 90
xiaoMing["english"] = 75
xiaoHong["chinese"] = 77
xiaoHong["english"] = 88
print(xiaoMing)
print(xiaoHong)
运行结果:
很方便得通过下表语法可以设置一些特别的属性值,在这个案例中,通过下标语法可以设置成员属性课程成绩classScore的字典键值。
Student(age: 18, name: "xiaoMing", classScore: ["chinese": 0])
Student(age: 16, name: "xiaoHong", classScore: ["chinese": 0])
Student(age: 18, name: "xiaoMing", classScore: ["english": 75, "chinese": 90])
Student(age: 16, name: "xiaoHong", classScore: ["english": 88, "chinese": 77])