Swift语言学习笔记(三)

103 篇文章 0 订阅
53 篇文章 0 订阅


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方法会在调用的时候立即完成拷贝。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值