在swift中, 结构体被重新定义, 它用于很多类所拥有的功能, 几乎可以和类媲美, 但是在存储数据方面有区别, 类是引用类型, 结构体是值类型, 所以要根据存储数据的类型和使用环境来选择不同的数据结构
类和结构体定义
struct Resolution {
var width = 0
var heigth = 0 //赋初值
}
class VideoMode {
var resolution = Resolution()
var interlaced = false
var frameRate = 0.0
var name: String? //name属性会被自动赋予一个默认值nil,意为“没有name值”,因它是一个可选类型。
}
生成结构体和类实例的语法非常相似:
let someResolution = Resolution()
let someVideoMode = VideoMode()
结构体和类的访问和OC一样, 都可以通过.语法,访问属性和子属性
someVideoMode.resolution.width //使用点语法访问
someVideoMode.resolution.width = 1024 //使用点语法赋值
注意:与 Objective-C 语言不同的是,Swift 允许直接设置结构体属性的子属性。上面的最后一个例子,就是直接设置了someVideoMode中resolution属性的width这个子属性,以上操作并不需要从新设置resolution属性。记不记得在OC当中, 你如果要修改一个结构体,, 例如CGRect, 你不可以直接修改frame.origin.y的值, 而是需要构造一个新的CGRect, 然后把这个修改好的CGRect赋值给原来的CGrect
CGRect frame;
frame.origin.x = 100; //这样是修改不了的
结构体和枚举是值类型
在 Swift 中,所有的基本类型:整数(Integer)、浮点数(floating-point)、布尔值(Booleans)、字符串(string)、数组(array)和字典(dictionaries),都是值类型,并且都是以结构体的形式在后台所实现。
在 Swift 中,所有的结构体和枚举都是值类型。这意味着它们的实例,以及实例中所包含的任何值类型属性,在代码中传递的时候都会被复制。
let tenEighty = VideoMode() //创建一个类并赋值给tenEighty
tenEighty.frameRate = 25.0 //修改tenEighty. tenEighty.frameRate的值
let alsoTenEighty = tenEighty //把tenEighty赋值给一个新的常量
alsoTenEighty.frameRate = 30.0 //使用新的常量修改frameRate的值
print(tenEighty.frameRate) //30.0
需要注意的是tenEighty和alsoTenEighty被声明为常量(let)而不是变量。然而你依然可以改变tenEighty.frameRate和alsoTenEighty.frameRate,因为这两个常量本身不会改变。它们并不储存这个VideoMode实例,在后台仅仅是对VideoMode实例的引用。修改其中一个的值会影响到另外一个, 由此可证明, 他们使用的是同一份数据, 即引用的是同一个对象. 所以,改变的是被引用的基础VideoMode的frameRate参数,而不改变常量的值.(这一点与OC不同)
Person *p = [[Person alloc] init];
p.name = @"小米";
Person *p1 = p;
p1.name = @"大米";
NSLog(@"%@, %@", p1.name, p.name); //大米, 大米
类和结构体的选择
在你的代码中,你可以使用类和结构体来定义你的自定义数据类型。
然而,结构体实例总是通过值传递,类实例总是通过引用传递。这意味两者适用不同的任务。当你的在考虑一个工程项目的数据构造和功能的时候,你需要决定每个数据构造是定义成类还是结构体。
按照通用的准则,当符合一条或多条以下条件时,请考虑构建结构体:
结构体的主要目的是用来封装少量相关简单数据值。
有理由预计一个结构体实例在赋值或传递时,封装的数据将会被拷贝而不是被引用。
任何在结构体中储存的值类型属性,也将会被拷贝,而不是被引用。
结构体不需要去继承另一个已存在类型的属性或者行为。
集合(Collection)类型的赋值和拷贝行为
Swift 中数组(Array)和字典(Dictionary)类型均以结构体的形式实现。然而当数组被赋予一个常量或变量,或被传递给一个函数或方法时,其拷贝行为与字典和其它结构体有些许不同。
以下对数组和结构体的行为描述与对NSArray和NSDictionary的行为描述在本质上不同,后者是以类的形式实现,前者是以结构体的形式实现。NSArray和NSDictionary实例总是以对已有实例引用,而不是拷贝的方式被赋值和传递。
注意:以下是对于数组,字典,字符串和其它值的拷贝的描述。 在你的代码中,拷贝好像是确实是在有拷贝行为的地方产生过。然而,在Swift 的后台中,只有确有必要,实际(actual)拷贝才会被执行。Swift 管理所有的值拷贝以确保性能最优化的性能,所以你也没有必要去避免赋值以保证最优性能。(实际赋值由系统管理优化)
var a = [1, 2, 3]
var b = a
var c = a
a[0] = 42
//修改原来的值, 不会对其他的值产生影响, 字典同样
println(a[0]) // 42
println(b[0]) // 1
println(c[0]) //1