Swift----函数 、 闭包 、 枚举 、 类和结构体 、 属性

时间:2024-06-18 18:37:14

1 数组排序

1.1 问题

本案例实现一个整型数组排序的函数,数组排序的规则由传递的规则函数决定。

1.2 方案

首先定义一个整型数组排序函数sortInts,该函数有一个整型数组类型的参数,该参数必须是输入输出参数inout,否则并不能修改数组的值。另外还有一个(Int,Int)->Bool函数类型的参数rule,该参数用于提供数组的排序规则。

然后实现函数sortInts,这里采用数组的冒泡排序算法来实现排序。

接下来实现一个数组排序的规则函数rule1,该函数是(Int,Int)->Bool类型,可以将该函数设置为sortInts函数rule1规则的默认值。

最后将一个整型数组a,传递给函数调用,就能实现数组a的排序。当然也可以自定义规则传递给函数sortInts。

1.3 步骤

实现此案例需要按照如下步骤进行。

步骤一:定义整型数组排序函数sortInts

首先定义一个整型数组排序函数sortInts,该函数有一个整型数组类型的参数,该参数必须是输入输出参数inout,否则并不能修改数组的值。另外还有一个(Int,Int)->Bool函数类型的参数rule,该参数用于提供数组的排序规则,代码如下所示:

  1. funcsortInts(inout data:[Int],rule:(Int,Int)->Bool) {
  2. }

然后实现函数sortInts,这里采用数组的冒泡排序算法来实现排序,代码如下所示:

  1. funcsortInts(inout data:[Int],rule:(Int,Int)->Bool) {
  2. forvari=0;i < data.count-1;i++ {
  3. forvar j=0;j<data.count-i-1;j++ {
  4. if rule(data[j], data[j+1]) {
  5. swap(&data[j], &data[j+1])
  6. }
  7. }
  8. }
  9. }

步骤二:实现规则函数

sortInts函数的rule参数是一个函数类型,需要调用时进行传递,该参数用于决定数组的排序规则,可以进行自定义,也就是由程序员来根据程序需求自定义排序规则。

接下来实现一个数组排序的规则函数rule1,该函数是(Int,Int)->Bool类型,可以将该函数设置为sortInts函数rule1规则的默认值,代码如下所示:

  1. func rule1(a:Int,b:Int)->Bool {
  2. return a > b
  3. }
  4. //函数类型作为参数传递
  5. funcsortInts(inout data:[Int],rule:(Int,Int)->Bool = rule1) {
  6. forvari=0;i < data.count-1;i++ {
  7. forvar j=0;j<data.count-i-1;j++ {
  8. if rule(data[j], data[j+1]) {
  9. swap(&data[j], &data[j+1])
  10. }
  11. }
  12. }
  13. }

最后将一个整型数组a,传递给函数调用,使用默认规则实现数组a的排序,代码如下所示:

  1. var a = [1,3,2,4,9,8,5,0,6,7]
  2. sortInts(&a)

运行结果如图-1所示:

Swift----函数 、 闭包 、 枚举 、 类和结构体 、 属性

图-1

当然也可以自定义规则传递给函数sortInts,代码如下所示:

  1. //自定义排序规则
  2. func rule2(a:Int,b:Int)->Bool {
  3. return a<b
  4. }
  5. sortInts(&a, rule: rule2)
  6. func rule3(a:Int, b:Int)->Bool {return a%3 > b%3}
  7. sortInts(&a, rule: rule3)

运行结果如图-2所示:

Swift----函数 、 闭包 、 枚举 、 类和结构体 、 属性

图-2

1.4 完整代码

本案例中,完整代码如下所示:

  1. importUIKit
  2. func rule1(a:Int,b:Int)->Bool {
  3. return a > b
  4. }
  5. //函数类型作为参数传递
  6. funcsortInts(inout data:[Int],rule:(Int,Int)->Bool = rule1) {
  7. forvari=0;i < data.count-1;i++ {
  8. forvar j=0;j<data.count-i-1;j++ {
  9. if rule(data[j], data[j+1]) {
  10. swap(&data[j], &data[j+1])
  11. }
  12. }
  13. }
  14. }
  15. var a = [1,3,2,4,9,8,5,0,6,7]
  16. sortInts(&a)
  17. a
  18. //自定义排序规则
  19. func rule2(a:Int,b:Int)->Bool {
  20. return a<b
  21. }
  22. sortInts(&a, rule: rule2)
  23. func rule3(a:Int, b:Int)->Bool {return a%3 > b%3}
  24. sortInts(&a, rule: rule3)

2 将Int数组转换为对应的String类型的数组

2.1 问题

如果需要将一个很长的闭包表达式作为最后一个参数传递给函数,可以使用尾随闭包来增强函数的可读性。本案例在Array的map方法中使用尾随闭包将一个Int类型的数组[16, 58, 510]转换为对应的String类型的数组["一六", "五八", "五一零"]。

2.2 方案

Array类型有一个map方法,唯一参数是一个闭包表达式,数组中的每一个元素调用用一次该闭包函数,并返回该元素所映射的值,具体的映射方式由闭包表达式决定。

当提供给数组闭包函数后,map方法将返回一个新的数组,数组中包含了与原数组一一对应的映射后的值。

2.3 步骤

实现此案例需要按照如下步骤进行。

步骤一:创建字典digiNames

创建一个数字和中文名映射的字典digiNames,代码如下所示:

  1. letdigitNames = [
  2. 0: "零", 1: "一", 2: "二", 3: "三", 4: "四",5: "五", 6: "六", 7: "七", 8: "八", 9: "九"]
  3. let numbers = [16, 58, 510]

步骤二:调用map方法

numbers数组调用map方法,该方法需要传递一个闭包表达式用于规定映射规则,这里采用尾随闭包的形式,代码如下所示:

  1. numbers.map {(var number) -> String in
  2. var output = ""
  3. while number > 0 {
  4. //字典下标返回一个可选值
  5. output = digitNames[number % 10]! + output
  6. number /= 10
  7. }
  8. return output
  9. }

map函数是数组的方法,可以迭代数组中每一元素传入闭包执行一次,并将执行后的结果做成一个数组返回回来,运行结果如图-3所示:

Swift----函数 、 闭包 、 枚举 、 类和结构体 、 属性

图-3

2.4 完整代码

本案例中,完整代码如下所示:

  1. importUIKit
  2. letdigitNames = [
  3. 0: "零", 1: "一", 2: "二", 3: "三", 4: "四",5: "五", 6: "六", 7: "七", 8: "八", 9: "九"]
  4. let numbers = [16, 58, 510]
  5. //map函数是数组的方法,可以迭代数组中每一元素传入闭包执行一次,并将执行后的结果做成一个数组返回回来
  6. let strings = numbers.map {(var number)->String in
  7. var output = ""
  8. while number > 0 {
  9. output = digitNames[number%10]!+output
  10. number/=10
  11. }
  12. return output
  13. }
  14. strings

3 定义商品条形码的枚举

3.1 问题

假设一个仓库跟踪系统需要利用两种不同类型的条形码来跟踪商品,有些商品上标有UPC-A格式的一维码,它是由三个整型数字组成。另外其他一些商品上标有QR格式的二维码,它是一个字符串,如图-4、图-5所示:

Swift----函数 、 闭包 、 枚举 、 类和结构体 、 属性

图-4

Swift----函数 、 闭包 、 枚举 、 类和结构体 、 属性

图-5

本案例要求使用枚举来表示商品条码并设置其关联值。

3.2 方案

首先把UPC-A码作为三个整型值的元组,把QR码作为一个任字符串存储起来,那么定义一个枚举Barcode并设置器关联值。

3.3 步骤

实现此案例需要按照如下步骤进行。

步骤一:定义枚举Barcode

定义一个枚举Barcode表示商品条形码,它有两个成员UPCA和QRCode,UPCA的关联值是一个包含三个整型值的元组类型,QRCode的关联值是一个String类型,代码如下所示:

  1. enum Barcode{
  2. case UPCA(Int, Int, Int)
  3. caseQRCode(String)
  4. }

枚举的定义不提供任何Int或String的实际值,只是定义而已。

步骤二:使用关联值

使用刚才定义的枚举类型Barcode创建一个新的变量productBarcode,并且赋给它两个成员的关联值,代码如下所示:

  1. varproductBarCode : Barcode = Barcode.UPCA(692, 530372375, 0)
  2. productBarCode = Barcode.QRCode("ABCDEFSFD")

不同的条形码可以使用一个switch语句来检查,代码如下所示:

  1. switchproductBarCode {
  2. case .UPCA(let(num, id, check)):
  3. println("这是条形码\(num)-\(id)-\(check)")
  4. case .QRCode(let pCode):
  5. println("这是二维码\(pCode)")
  6. }

然后调用函数,运行结果如图-6所示:

Swift----函数 、 闭包 、 枚举 、 类和结构体 、 属性

图-6

3.4 完整代码

本案例中,完整代码如下所示:

  1. importUIKit
  2. //关联值
  3. enum Barcode{
  4. case UPCA(Int, Int, Int)
  5. caseQRCode(String)
  6. }
  7. varproductBarCode : Barcode = Barcode.UPCA(692, 530372375, 0)
  8. productBarCode = Barcode.QRCode("ABCDEFSFD")
  9. switchproductBarCode {
  10. case .UPCA(let(num, id, check)):
  11. println("这是条形码\(num)-\(id)-\(check)")
  12. case .QRCode(let pCode):
  13. println("这是二维码\(pCode)")
  14. }

4 定义几何形状的结构体

4.1 问题

属性分为存储属性和计算属性,存储属性就是用常量或变量保存的属性值。计算属性的值是通过计算得出的。

按如下要求完成本案例:

1)定义一个Point结构体,用于表示点坐标(x,y);

2)定义一个Size结构体,用于表示形状的长和宽(width,height);

3)定义一个Rect结构体,用于表示有原点和尺寸的矩形,还提供一个表示中心点center的计算属性;

4)创建一个Rect类型的实例square,并设置和修改center属性移动矩形,如图-7所示:

Swift----函数 、 闭包 、 枚举 、 类和结构体 、 属性

图-7

4.2 方案

首先定义Point结构体和Size结构体,Point结构有两个存储属性x和y,用于表示点坐标。Size结构体也有两个存储属性width和height,用于表示长宽。

然后定义矩形Rect结构体,该结构体有两个存储属性一个是Point类型的origin,用于表示原点坐标,另一个是Size类型的size,用于表示矩形的长宽。

Rect结构体还有一个Point类型的计算属性center,用于表示矩形的中心点,需要提供getter和setter方法获取和设置其值。

最后创建一个Rect实例square,设置和修改center属性,查看输出结果。

4.3 步骤

实现此案例需要按照如下步骤进行。

步骤一:定义Point和Size结构体

首先定义Point结构体和Size结构体,Point结构有两个存储属性x和y,用于表示点坐标。Size结构体也有两个存储属性width和height,用于表示长宽,代码如下所示:

  1. struct Point {
  2. //存储属性
  3. var x = 0.0
  4. var y = 0.0
  5. }
  6. struct Size {
  7. //存储属性
  8. var width = 0.0
  9. var height = 0.0
  10. }

步骤二:定义Rect结构体

然后定义矩形Rect结构体,该结构体有两个存储属性一个是Point类型的origin,用于表示原点坐标,另一个是Size类型的size,用于表示矩形的长宽,代码如下所示:

  1. structRect {
  2. //存储属性
  3. var origin = Point()
  4. var size = Size()
  5. }

Rect结构体还有一个Point类型的计算属性center,用于表示矩形的中心点,需要提供getter和setter方法获取和设置其值,代码如下所示:

  1. structRect {
  2. //存储属性
  3. var origin = Point()
  4. var size = Size()
  5. //计算属性
  6. varcenter:Point {
  7. get {
  8. letcenterX = origin.x + size.width/2
  9. letcenterY = origin.y + size.height/2
  10. return Point(x: centerX, y: centerY)
  11. }
  12. set(newCenter) {
  13. origin.x = newCenter.x - size.width/2
  14. origin.y = newCenter.y - size.height/2
  15. }
  16. }
  17. }

步骤三:创建square实例

创建一个Rect实例square,原点坐标设置为(0.0,0.0),长宽设置为(10.0,10.0),可以通过点运算调用getter方法获取到center属性的值,代码如下所示:

  1. var square = Rect(origin: Point(x: 0.0, y: 0.0), size: Size(width: 10.0, height: 10.0))
  2. letcenterSquare = square.center

可以看到center的值为(5.0,5.0),运行结果如图-8所示:

Swift----函数 、 闭包 、 枚举 、 类和结构体 、 属性

图-8

然后重新设置center的值(15,15),设置属性center的值会调用setter来修改该属性origin的值,代码如下所示:

  1. square.center = Point(x: 15, y: 15)

可以看到此时square的origin属性的值为(10,10),运行结果如图-9所示:

Swift----函数 、 闭包 、 枚举 、 类和结构体 、 属性

图-9

4.4 完整代码

本案例中,完整代码如下所示:

  1. importUIKit
  2. struct Point {
  3. //存储属性
  4. var x = 0.0
  5. var y = 0.0
  6. }
  7. struct Size {
  8. //存储属性
  9. var width = 0.0
  10. var height = 0.0
  11. }
  12. structRect {
  13. //存储属性
  14. var origin = Point()
  15. var size = Size()
  16. //计算属性
  17. varcenter:Point {
  18. get {
  19. letcenterX = origin.x + size.width/2
  20. letcenterY = origin.y + size.height/2
  21. return Point(x: centerX, y: centerY)
  22. }
  23. set(newCenter) {
  24. origin.x = newCenter.x - size.width/2
  25. origin.y = newCenter.y - size.height/2
  26. }
  27. }
  28. }
  29. var square = Rect(origin: Point(x: 0.0, y: 0.0), size: Size(width: 10.0, height: 10.0))
  30. letcenterSquare = square.center
  31. square.center = Point(x: 15, y: 15)