Han的小站

一徐清风,半指烛光,觥筹已净,只余茶香。残卷一章,妙趣非常,忽闻帘响,愿闻其详?...

Swift语言学习笔记(三)


54. Swift中闭包的语法:

{ ( parameters ) -> returnType in

    statements

}

闭包的参数同样可以使常量、变量、inout类型的,但是不能提供默认值。参数列表和元组也可以在闭包中使用。

例如下面的闭包定义用来返回较大值:

{ (a : Int, b : Int) -> Int in return a >= b ? a : b }

当闭包的参数和返回值类型能够被推测出来时(大多数情况下都能被推测出来),可以省略掉参数类型和返回值,例如上面的例子可以简化为:

{ a, b in return a >= b ? a : b }

如果闭包中只有一条语句,则可以省略掉return关键字,例如上面的例子:

{ a, b in a >= b ? a : b }

Swift中还为我们提供了参数的快捷名称:$0$1$2…(数字表示参数的位置,第一个参数为$0),使用快捷名称来定义闭包,可以省略掉in关键字以及前面的参数定义,上面的例子可以继续优化为:

{ $0 >= $1 ? $0 : $1 }

55. 如果闭包作为一个函数的最后一个参数出现,在调用的时候可以将闭包写到函数参数的括号外面去,例如我们用闭包来定义一个冒泡排序:

func sort(nums : Int[], comp : (Int, Int) -> Bool, swap :(inout Int, inout Int) -> ()) -> Int[] {

    var count = countElements(nums) - 1

    for var i = 0; i < count; i++ {

        for var j = 0; j< count - i; j++ {

           if comp(nums[j], nums[j+1]) {

               swap(&nums[j], &nums[j+1])

           }

        }

    }

   

    return nums

}

var arr = [1, 6, 8, 2, 7, 0, 5, 3, 9, 4, 6, 2]

println(sort(arr, >) { (inout a : Int, inout b : Int)-> () in

    if a >= b {

        var temp = a

        a = b

        b = temp

    }

})

如果函数唯一的一个参数是闭包表达式,则调用的时候可以不写省略掉圆括号“()”。

56. 闭包能够记录包含闭包的上下文中定义的变量和常量,并且能够在闭包代码块中修改和访问它们(甚至当这些变量和常量随着作用域的更改不再有效)。例如:

func makeIncrementor(amount : Int) -> ()->Int {

    var total = 0

    var incrementor = {()-> Int in

        total += amount

        return total

    }

   

    return incrementor

}

var inc = makeIncrementor(10)

println(inc())       //输出10

println(inc())       //输出20

println(inc())       //输出30

这里由于创建出来的incrementor函数不会修改amount参数,所以新创建出来的incrementor方法会拷贝一个amount的副本,原来的amount会随着makeIncrementor函数的结束而被释放,但是incrementor函数中确实修改了total变量的值,因此它会保留total变量的一个引用,从而保证total不会随着makeIncrementor函数的结束而被释放掉。

57. Swift中函数和闭包是引用类型。

58. Swift中的枚举类型定义:

enum Direction {

case North

case South

case East

case West

}

也可以在一个case中写多个枚举成员:

enum Direction {

case North, South, East, West

}

59. 对于枚举类型,可以在定义中允许枚举值保存附加信息,例如:

enum Product {

    case Product1(Float,Int)       //Discount, Price

    case Product2(Float,String)    //Discount, Gifts

}

var product1 = Product.Product1(0.8, 120)

var product2 = Product.Product2(0.75, "Product3")

在Switch语句中可以使用变量中保存的信息:

switch product {

case Product.Product1(let discount, let price):

println(“Product1 with a discount of \(discount), and theprice is \(price)”)

case Product.Product2(let discount, let gift):

    println(“Product2 with a discount of\(discount), and with \(gift) as a gift”)

}

60. 枚举类的原生数据(raw value)可以是字符串、字符、整型或者浮点型,在定义的时候在枚举名后面加上冒号和类型来声明,如果原声数据类型是整型,那么对于没有指定的枚举成员会自动递增。例如:

enum ASCIIControlChar : Character {

case Tab = “\t”

case LineFeed = “\n”

case ReturnToLineStart = “\r”

}

注意Swift中字符也是使用双引号来定义的。

enum CompareResult : Int {

case LessThan = 0

caseEqual                   //自动增加为1

caseGreaterThan        //自动增加为2

}

使用toRaw()方法来将枚举值转换为对应的原声数据:

var cmpResult = CompareResult.Equal.toRaw()

使用fromRaw()方法来将原生数据转换为枚举值:

var cmpResult = CompareResult.fromRaw(1)

fromRaw方法返回一个可选类型,当转换失败的时候,返回nil

61. Swift中的结构体中也可以定义方法以及构造函数(或者说初始化函数),但是不能定义析构函数。结构体没有深浅拷贝之说,在赋值的时候都是完全拷贝出一个新的结构体赋给目标变量,类在赋值的时候,如果不使用深拷贝,则只传递引用,结构体无继承。

62. Swift中的结构体在定义好之后,默认会生成一个初始化方法,这个初始化方法需要指定参数名来调用,且参数的顺序要喝结构体中的声明顺序一致:

struct Student {

    var name : String

    var age : Int

    var score : Int

}

var s1 = Student(name : "Someone", age : 15, score: 95)

对于Swift中的类,如果不指定初始化函数的话,不会自动生成类似上面的初始化方法。

63. 对于Swift中的结构体和类,如果在定义的时候所有的属性都给出了初始值,则Swift会自动为其创建一个不含参数的初始化方法,例如:

struct Student {

    var name : String = ""

    var age : Int = 0

    var score : Int = 0

}

var s = Student()

如果一个以上的属性没有初始值,则不会生成不含参的构造方法。

64. Swift中的Dictionary在拷贝或者传参的时候与结构体相同,会深拷贝一份完全相同的Dictionary对象。如果Dictionary的键值中有引用类型,则会拷贝出一个引用来,如果键值都是值类型,则拷贝相同的值。

65. Swift中的Array在拷贝或者传参的时候,不会立即复制一份完全相同的Array对象,而是先临时共享公共的内容,当程序将要修改其中某个Array的元素的时候,另一个Array也同样被修改了(或者说因为两个Array指向同一个共享的内容,所以修改一个也会影响另一个)。只有当Array的大小(元素数量)发生变化的时候,才会完成内容的拷贝,两个Array此时才会各自拥有自己的内容,拷贝的效果和Dictionary对象相同:值类型完全拷贝,引用类型拷贝引用值。例如:

var array1 = [1, 2, 3, 4]

var array2 = array1

array1[3] = 5

println(array2)

这个例子array2输出1,2,3,5,也就是修改array1的第四个元素同时也影响了array2,即由于修改没有改变数组的大小,两个数组共享相同的内容。接着看下面的例子:

var array1 = [1, 2, 3, 4]

var array2 = array1

array1 += 5

array1[3] = 5

println(array2)

输出结果为1,2,3,4,因为在array1中加入元素(“5”)的时候,array1从共享的内容中拷贝出了一份内容,而array2仍然指向原来共享的内容(此时已经不共享了),因此没有受到array1[3]=5这句的影响。

66. 对于Array来说,如果希望数组在复制的时候,不共享共同的内容,除了刻意地修改其大小外,还可以调用unshare()方法(注意:常量数组不能调用unshare()方法),例如:

var array1 = [1, 2, 3]

var array2 = array1

array1.unshare()     //也可以调用array2.unshare()

array1[0] = 5

println(array2)         //输出1, 2, 3

此外,还可以使用copy方法来强制完成拷贝:

var array1 = [1, 2, 3]

var array2 = array1.copy()

array1[0] = 5

println(array2)         //输出1, 2, 3

unsharedcopy比起来要是一个更好的选择,unshare方法只会在需要的时候进行拷贝,而copy方法会在调用的时候立即完成拷贝。

阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qwertyupoiuytr/article/details/53997382
文章标签: IOS Swift
想对作者说点什么? 我来说一句

Go 学习笔记 第四版

2015年01月19日 1.32MB 下载

go语言学习笔记

2018年03月06日 897KB 下载

Go 学习笔记中文 pdf

2017年11月24日 1.15MB 下载

swift语言快速入门

2014年09月09日 2.11MB 下载

没有更多推荐了,返回首页

不良信息举报

Swift语言学习笔记(三)

最多只允许输入30个字

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭