Swift语言学习笔记(三)

news/2024/7/20 21:51:48 标签: IOS, 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方法会在调用的时候立即完成拷贝。


http://www.niftyadmin.cn/n/878542.html

相关文章

五子棋人机对战_人机对战!运动下棋!“约战普陀”智力运动系列挑战赛收官! | 文末福利...

金秋十月&#xff0c;2019年上海城市业余联赛“约战普陀”智力运动系列挑战赛迎来收官战。昨天下午&#xff0c;围棋、五子棋总决赛暨940棋牌挑战赛在长风大悦城进行。比赛现场&#xff0c;8位小选手面前只有一个棋盘&#xff0c;但是并没有另外一位棋手。这是怎么回事儿呢&…

js 运行中断停止_如何终止 JS 脚本的运行

在很多其他语言比如 PHP 当中&#xff0c;存在 exit 函数来中止程序的运行。很遗憾的是 JavaScript 没有。因此我们需要自己模拟出这么一个 “exit” 功能。我们知道&#xff0c;break是 JavaScript 中合法的中断语句&#xff0c;但其只适用于循环和 switch 语句&#xff0c;此…

Swift语言学习笔记(四)

&#xfeff;&#xfeff;67. 如果结构体&#xff08;Struct&#xff09;的实例被声明为常量的话&#xff0c;就不能对其属性进行修改&#xff0c;即使是var类型的属性。而对于类&#xff08;Class&#xff09;来说则不是这样&#xff0c;如果一个类的实例被声明为常量&#xf…

Swift语言学习笔记(五)

&#xfeff;&#xfeff;80. Swift中的类没有默认的父类&#xff0c;如果在定义一个类的时候没有指定其父类&#xff0c;则这个类就是一个基础类&#xff0c;不继承任何其他类。 81. Swift中类的继承关系适用冒号来声明&#xff0c;和C#中一样。在子类中重写父类方法适用over…

vue仿今日头条_vue 仿今日头条

vue 仿今日头条为了增加移动端项目的经验&#xff0c;近一周通过 vue 仿写今日头条&#xff0c;以下就项目实现过程中遇到的问题以及解决方法给出总结&#xff0c;有什么不正确的地方&#xff0c;恳请大家批评指正^ _ ^&#xff01;&#xff0c;代码仓库地址为 github一、实现…

kindlefire刷安卓系统_测试kindle fire 刷安卓4系统用手机GPS模块导航

此文涉及软件已提供下载&#xff0c;均在软件和镜像下载中的phone目录中&#xff0c;其中高德导航是学习版本(这个大家都懂吧)用户名和密码获取设备到手&#xff0c;kindle fire 一台&#xff0c;Moto XT 316一台&#xff0c;XT316刷成安卓2.3.5版本。kindle fire 刷成了安卓4.…

Swift语言学习笔记(六)

97. 可选链&#xff08;optional chaining&#xff09;的例子&#xff1a; class A { var m : Int 10 } class B { var a : A? } class C { var b : B? } var c C() var k c.b?.a?.m println(k) 上面的例子中&#xff0c;我们在为变量k赋值的时候&#xff0c;使用的是c.…

sublime存模板_使用SublimeTemp自定义C文件模板

1. 安装SublimeTmpl插件通过package control 安装 或 Git clone https://github.com/kairyou/SublimeTmpl 到/Sublime Text 3/Packages文件夹下2. 自定义模板进入 /Sublime Text 3/Packages\User\SublimeTmpl\templates目录下创建自己的模版(可参考/Sublime Text 3/Packages/Su…