swift 基础:
swift 是完全由一个工程师设计完成,编译型语言和脚本语言的结合,编译型语音就是需要保证每一行都通过编译才能够运行,编译语言功能更强大,脚本语言功能更灵活,不需要代码完全通过编译,能执行一行代码就执行一行代码,直到执行到错误的代码行后,才停止运行代码
swift 的首席架构师是 chris lattner,是 llvm 项目的主要发起人和作者之一(llvm 项目即编译器),clang 编译器的作者。
swift 基础语法:
源文件拓展名是 .swift
不需要编写 main 函数,swift 代码是按顺序执行的,最前面的代码就是程序的入口
swift 可以不写分号,也可以写
多行注释可以嵌套了,不会报错
let 常量,var 变量,都可以一行声明多个,
如果代码中有 override 关键字,那么说明这个方法是继承自父类的方法
swift 中使用 “.” 点来调用方法,而不是中括号,
xcode 中的 playground 可以即时看到一些简单代码的效果
swift 中的字符串 使用 \() 进行插值操作;可以使用 + 号来进行字符串的拼接,但是只能是字符串和字符串进行拼接,可以有对应方法将非字符串转成字符串类型的变量
命名还是不能以数字开头
新加了两种数据类型:Tuple:元祖类型,Optional:可选类型,数据类型名强制开头大写
swift 强制变量使用之前必须初始化,swift 不会自动为变量赋初始值
对于数据类型,可以使用 min 和 max 方法来获得这个数据类型的最小值和最大值
对于 int 类型,有8,18,32,64位 不同的类型,如果省略位数不写,使用 int 自适应当前系统的位数,通常不用在意这一点内存的使用,通常使用 int 自适应
swift 是强类型语音,是类型安全语言,不同类型的数据是不能够进行操作的。包括位数不同,
swift 默认是不支持数据溢出的
double 类型至少有15位小数,float 至少有6位小数,默认是 double,表示指数的方式有两种,一种是 e,对应十进制,10的 x 次方,一种是 p,对应16进制,2的 x 次方,10进制小数可以没有指数,也可以有,但是16进制的小数一定要有指数后缀
使用 typealias来定义类型的别名,alias 就是别名,化名的意思,类似于 c 语言的 typedef,在 c 中,是这么写的 typedef int myint,即 myint 就是 int 类型的别名了,在 swift 中是这么写的,typealias Myint = Int,记住 swift强制类型名 首大写
swift 运算符多了一些,比如范围运算符,溢出运算符,和 c 和 oc 不一样的是,swift 的赋值运算符没有返回值,在 c 或者 oc 中,赋值运算符是有返回值的,比如 int a = 10;int b = a = 10;是合法的,因为 a = 10 是有一个返回值的,可以赋值给 b,在 swift 中是不允许的,因为在 c 中,只要非0就是真,swift 为了防止把 == 误写为 = ,设置了这么一个机制:赋值运算符没有返回值。
还有求余运算符,swift 中能够支持小数的取余操作
bool 类型,只有两种取值:true,false,c 中只要非0都是就是真,但是 swift 中只有 true 才是真,只有这么一个真,假也只有 false 才是假,0也不是假,swift 是强类型语言,bool 就是 bool,int 就是 int,是完全不同的类型,不再是 c 中的模糊界限的语言。这点要注意。
范围运算符,有两种,闭合范围“...”和半闭合范围“..<”,多用于 for 循环中。
溢出运算符,只能用在整形数值中,以&开头的就是溢出操作符,当数据溢出之后,不会报错,只会取对应的位数的值,这就是溢出运算符的作用,包括上溢出和下溢出,就是如果溢出了就在最大值和最小值之间来回循环,还有除0溢出,使用溢出除法就可以除以0
元祖运算符,元祖类型是由 N 个任意类型的数据组成的类型,组成元祖的成员称为元素,N>=0,可以有空元祖,元素可以是用“。”来访问元素,还可以使用下标来访问元素,访问方式就像结构体和数组的混合,使用元素名称或者元素位置都可以访问对应的元素,元祖也有 var 和 let 的区分,可以输出整个元祖来查看所有的元祖元素,直接打印元祖变量或者常量名就可以打印了,元素的名称也是可以省略的,元祖的元素是有顺序的,元素可以是任意类型,但是不能够修改对应位置的元素的类型,只能够修改这个位置的元素的值,并且如果明确指定了元素的类型,那么就不能够再同时指定这个元素的名称,元素名称和元素类型是不能够共存的,如果在对应的元素位置使用“_”,表示忽略掉这个位置的元素,
swift 的流程控制,所有的流程控制之后都必须有大括号,在 c 或者 oc 中可以没有大括号,比如 if,swift 中任何流程控制都必须有大括号。新加入的有 for in 循环,比如 for a in b{。。。},b 是一个范围,a 是这个范围内的每一个最小分块,这个范围内有多少分块,就执行多少次循环,每次都会赋值给 a,每一次循环执行一次 大括号中的代码,如果不需要使用范围中的值,可以使用“_”来忽略 a 的值,定义 a 有时候也会消耗一定的内存,要注意的是 a 在这个循环中是一个常量,而不是变量,所以每一次循环都会新建一个常量 a,如果不需要使用,那么最好用“_”来代替。“_”可以认为是忽略这个位置的值或者这个位置上可以取对应类型的所有值
switch:swift 中的 switch 可以匹配数值,字符串,并且可以省略 break 不写,如果需要穿透执行就使用 fallthrough 关键字来声明穿透一个 case 语句或者 default 语句,使用 fallthrough 要注意的是之后的 case 或者 default 语句中不能够定义常量或者变量,并且在 swift 中的 switch 的每一个 case 中都必须有执行语句,如果要忽略某个或者某些 case,那么在这些 case 中的语句写成 break 即可,每个 case 可以完成多条件匹配,每个条件使用逗号隔开即可,因为没有穿透执行,所有使用多条件匹配更方便,case 还能够进行范围匹配,但是匹配的值只能是一个值,这个值可以是 case 中的一个范围之内,并且 case 要有完备性,所有 switch 要匹配的值的可能性都要考虑到,不一定要写 default,前提是所有的 case 实现了完备性,如果没有,就必须是用 default 来实现完备性,switch 的匹配还能够是元祖,元祖意味着是可以有多种类型的元素的, 那么 case 中的条件也是元祖,任意的元祖。并且在 case 匹配的同时,可以在 case 条件 中的某个值绑定给一个特定的常量或者变量,以便在 case 的执行语句中使用,类似于使用“_”,不同的是这个忽略的值可以通过变量名或者常量名明确在语句中使用。switch 中还新增了一个 where,通过 where 可以增加一些匹配的约束条件,
标签,用于跳出循环时指示编译器是跳出的哪个循环。用法是 标签名:循环,一般为了方便查看,冒号之后会换行再写循环。
swift 中的函数,和 c 和 oc 中的也有略微不同,格式是:func 函数名 (形参列表)-> 返回值类型{。。。。函数语句。。。。},在形参列表中,定义一个形参是先写形参名,加上冒号之后再写形参类型,如 形参名1:形参类型,。。。
和 oc 中顺序是相反的。函数如果没有返回值,那么 swift 中的返回类型有3中写法,第1种是写 Void 类型,第2中是只写()空括号,第3种是什么都不写,但是如果是没有参数,那么参数列表的小括号不能够省略。返回类型还能够返回一个元祖类型的数据,返回值中的元祖中的元素名可以不写(也可以写,如果有元素名那么就可以通过元素名来访问元素),只写元祖元素的数据类型。swift 函数中还有一个新特性,外部参数名,用于修饰参数,可以在传入参数时可以更明确这个参数的实际意义,因为在调用函数时是不使用形参名的,形参名只在函数内部使用,如果加入了外部参数名,就可以更明确的知道这个参数所代表的意思,外部参数名写在形参名之前即可,如果希望外部参数名和形参名相同,那么形参名前加上#号就可以定义一个同名的外部参数名了,如果定义了外部参数名,那么在调用函数时一定要使用外部参数名。swift 中函数还有默认参数值的机制,可以在定义形参的时候加入一个默认参数值,那么再使用这个函数的时候这个参数可以不传入实际参数值,而是使用默认参数值,如果传入了实参,那么就会覆盖掉默认值,并且带有默认值的形参,系统会自动定义一个同名的外部参数名,不用再加#号,也就意味着再传入对应的实参时,必须使用这个外部参数名,如果使用的默认参数值,也就是没有传入实参,那么就不用使用外部参数名了,如果不想写外部参数名,那么可以使用“_”来代替 i这个外部参数名,在调用函数传入实参时就可以不写这个外部参数名了,“_”表示忽略一切。在 c++ 中有这么一个机制,在 oc 和 java 中都没有。参数还有常量参数和变量参数,默认情况下都是常量参数,在函数体内部是不能够修改的,意思是指传入一个实参后,把实参的值赋值给了形参,那么这形参的值是不能够在函数中进行修改的,在 c 中是可以修改形参的值的,如果需要修改形参的值,那么需要定义为变量参数,默认是 let ,使用 var 定义参数就是表示是变量参数,可以在函数中修改。inout 修饰参数类似于 c 中的指针,参数是值传递的,使用 inout 可以实现引用传递,swift 中弱化了指针的概念,尽量不使用指针,如果要把一个实参传递给一个 inout 形参,那么实参名前要加上&符号,一定要加,但是官方没有明确声明这是一个取地址符号(实际就是)。如果定义了一个 inout 参数,那么就不用也不能在定义是 let 或者 var 参数了。并且 inout 参数不能够传入常量或者字面量作为参数值,字面量就是直接写出来的数值,比如10,20。。。,常量就是 let 常量,因为 inout 的初衷就是用于更改值的,如果传入不能更改的值没有任何意义。并且inout 参数不能够定义默认值,不能够是可变参数。inout 参数可以实现函数的多返回值,比如定义返回类型是元祖类型,比较灵活。
此博客系统没有自动定时保存草稿的功能,遗失大段内容。。。
遗失部分内容如下:
swift 新加符号 (xxx ??xxx),选并操作符
元祖
json,传输格式的一种
数组
.......
字典:字典是无序的,增加字典的键值对或者修改键值对都可以通过下标进行操作。还有一个 updataValue 的方法来进行更新值,remove 方法来进行键值对的移除,这两个方法都有一个可选的返回值,遍历字典的方法,创建字典同样可以通过构造器来创建,字典中的 key 类型一定要是可哈希的,基本的数据类型都是可哈希的,哈希算法几乎是不可逆的,MD5的加密算法就是常见的哈希算法之一,哈希是把某个值进行处理,生成独一无二的一个哈希值,然后通过这个值就可以快速找到对应的实际值。
控制流,多了 for in ,并且 switch 可以匹配元祖,并且在 case 中可以进行“值绑定”,“值绑定”就是把要匹配的值进行传递给一个在 case 中定义的变量或者常量(如果要使用 fallthrought,那么就不可以在下个 case 中定义变量或者常量),并可以使用这个变量或者常量,注意的是默认是局部变量或者常量,只在当前这个 case 语句中生效,如果在 case 中定义了变量或者常量,如果没有定义 where 语句进行限制的话,那么编译时会把 switch 中要匹配的值传给第一个 case 中定义的变量,还有一个 where 语句可以进行而外的条件限制,当 where 中的判断语句为真时,就匹配当前的 case,并将switch 中的值传递给 case 中的变量或者常量。swift 中的所有控制语句都要用大括号。定义标签,精确控制循环的跳出,格式 lable 循环名:循环语句
二元运算符操作元素的两边都要加上空格, control + i, 自动缩进代码
函数,argument:实参,parameters:形参,在 swift 中函数的参数和返回值是比较灵活的,如果是空形参,那么小括号也还是要写,返回值类型也可以是可选的。函数中的外部参数名和本地参数名,外部参数名就是一个形参的别名,在调用函数的时候可以更明确要传入的参数的作用,只要定义了外部参数名,调用函数时一定要使用外部参数名,还有可以给形参设置默认值。还可以使用#号来修饰参数名,生成一个同名的外部函数名,#也称为哈希符号,定义默认的形参值在定义形参的时候定义即可,默认的值可以覆盖也可以省略。函数还有可变参数的特性,即参数的个是不确定的,但是类型必须是要一致,使用“参数类型...”即可表示一个可变个数的参数类型,这个参数的类型都是一致的,但是个数可变,并且可变参数一定要放在形参列表的最后,即只能定义一个可变参数,最多一个,这个可变参数相当于一个该类型的可变数组,形参名就是数组名。还有 var 参数,函数的形参默认是常量,接收了实参的值后就不能再更改,使用 var 来修饰形参就可以定义一个可变的形参。还有 inout 参数,这个参数相当于传入一个指针,但是官方没有明确表明是传入了指针,虽然实际就是指针,inout 要配合&符号来使用,&符号用于修饰传入实参的值,inout 不能有默认值,不能修饰为 var 或者 let。函数类型,某个函数的类型就是这个函数的形参列表类型+上返回值类型,函数类型 = 每个形参的类型 + 返回值的类型。在函数类型中,如果为空形参或者是没有返回值,都要在对应位置写上剪头和小括号,如下: () -> (),如果返回值不为空,那么就不要用写返回值的小括号了,函数类型也是常用的类型之一,只要是类型,就可以定义这个类型的变量或者常量,和普通数据类型一样使用,把某个类型的数据赋值给一个给类型的数据,比如:let a: Int = 1,换成函数类型就是 let a: 函数类型 = 这个类型的函数名,相当于起了一个函数的别名,又或者可以更灵活的调用函数,注意=号右边的函数名之后不要加括号,加上括号就是表示调用函数了,函数类型也可以省略不写,因为系统可以根据=号右边推断出变量的类型,函数类型还可以被当成一种类型在其他的函数中被使用,就是形参的数据类型一样,形参的类型也可以是函数类型,函数类型的主要作用是用于联系两个函数之间的互动,减少函数之间的耦合性,通过类型类进行互动,而不是特定的一个函数名来进行互动,函数类型也可以是返回值的类型,返回一个函数类型,只是返回这个类型的函数,这个函数中并没有参数,相当于对函数进行包装,简化函数的使用。swift 中还有全局函数和嵌套函数,一般的都是全局函数,函数中的函数是嵌套函数,嵌套函数对于外部是不可见的,
闭包,又或者可以称为代码块,核心的功能就是捕获,或者抓取一些变量或者常量,函数包括全局函数和嵌套函数都是一种特殊的闭包或者代码块。之所以使用闭包是为了更方便的对常量或者变量进行处理操作,不用在写函数名或者形参名或者返回值名之类,简化代码,注意函数也是闭包的一种,函数名就相当于闭包,当需要传递闭包的时候可以直接传递一个函数名,闭包和函数的不同就是闭包没有名字,有形参列表,形参列表写在大括号内,返回类型也写在大括号内,并且返回类型之后跟着一个关键字 “in” ,in 之后是闭包的代码。闭包的作用就是简化函数的写法,因此闭包的参数类型是可以省略的,闭包的返回语句 return 也是可以在某些情况下省略的,同样的闭包中的 -> 返回值类型也是可以在某种情况下省略的,并且参数还能够进行简写,使用$开头的就是简化参数的写法。挂尾闭包是指,当某个函数需要传入一个闭包作为参数时,可以把闭包当成最后一个形参(如果没有可变个数的形参),这时候就可以把这个作为参数的闭包整个提取出来,写在这个函数的尾部,也就是写在函数的形参列表的小括号之后,方便阅读,如果这个函数只有一个参数,并且这个参数是一个闭包,把这个闭包提取出来挂尾时,这个函数的形参列表的小括号可以省略不写.只要在大括号内出现 in,要么是 for in 循环,要么这个是个闭包,闭包的值捕获,在闭包周围的变量或者常量可以被这个闭包捕获,即使闭包所在的函数执行完毕之后,闭包中捕获的值依然有效,可以继续使用,嵌套函数就是闭包的值捕获的体现,嵌套的函数可以访问外部函数的变量,形参等,只要记住闭包就是简化函数的书写,就可以很好理解了,前提之一是这个值是在闭包中使用了的,即被闭包捕获了的,因为闭包是一种引用类型,所以要注意了,在闭包中被捕获相当于加了一个强引用,在处理内存时要考虑到这个问题,
重载操作符,操作符也是一个函数,函数也是一个闭包,当需要传入一个闭包的地方,某些情况下甚至可以直接传入一个操作符就可以了,大于等于小于加减乘除等等,
枚举:swift 中的枚举增加了很多功能,可以有枚举的方法,枚举的属性,枚举的协议等等,枚举可以搭配 switch 来进行使用,功能强大。枚举的关联值,枚举中还有原始值,在定义枚举时就可以定义原始值,定义原始值要同时也要定义枚举的值类型,定义了一个原始值,这个枚举属性之后的值都会自动定义原始值,+1,可以使用 toRaw 的方法来查看枚举变量的原始值是什么