iOS开发系列Swift语言总结.docx
- 文档编号:4921216
- 上传时间:2022-12-11
- 格式:DOCX
- 页数:47
- 大小:38.02KB
iOS开发系列Swift语言总结.docx
《iOS开发系列Swift语言总结.docx》由会员分享,可在线阅读,更多相关《iOS开发系列Swift语言总结.docx(47页珍藏版)》请在冰豆网上搜索。
iOS开发系列Swift语言总结
iOS开发系列--Swift语言
2015-08-1012:
09byKenshinCui,26622阅读,57评论,收藏,编辑
概述
Swift是苹果2014年推出的全新的编程语言,它继承了C语言、ObjC的特性,且克服了C语言的兼容性问题。
Swift发展过程中不仅保留了ObjC很多语法特性,它也借鉴了多种现代化语言的特点,在其中你可以看到C#、Java、Javascript、Python等多种语言的影子。
同时在2015年的WWDC上苹果还宣布Swift的新版本Swift2.0,并宣布稍后Swift即将开源,除了支持iOS、OSX之外还将支持linux。
本文将继续iOS开发系列教程,假设读者已经有了其他语言基础(强烈建议初学者从本系列第一章开始阅读,如果您希望从Swift学起,那么推荐你首先阅读苹果官方电子书《theswiftprogramminglanguage》),不会从零基础一点点剖析这门语言的语法,旨在帮助大家快速从ObjC快速过度到Swift开发中。
即便如此,要尽可能全面的介绍Swift的语法特点也不是一件容易的事情,因此本文将采用较长的篇幅进行介绍。
创建一个命令行程序如下:
importFoundation
/**
*Swift没有main函数,默认从toplevelcode的上方开始自上而下执行(因此不能有多个toplevel代码)
*/
println("Hello,World!
")
从上面的代码可以看出:
Swift没有main函数,从toplevelcode的上方开始往下执行(就是第一个非声明语句开始执行[表达式或者控制结构,类、结构体、枚举和方法等属于声明语句]),不能存在多个toplevelcode文件(否则编译器无法确定执行入口,事实上swift隐含一个main函数,这个main函数会设置并调用全局“C_ARGCC_ARGV”并调用由toplevelcode构成的top_level_code()函数);
Swift通过import引入其他类库(和Java比较像);
Swift语句不需要双引号结尾(尽管加上也不报错),除非一行包含多条语句(和Python有点类似);
数据类型
Swift包含了C和ObjC语言中的所有基础类型,Int整形,Float和Double浮点型,Bool布尔型,Character字符型,String字符串类型;当然还包括enum枚举、struct结构体构造类型;Array数组、Set集合、Dictionary字典集合类型;不仅如此还增加了高阶数据类型元组(Tuple),可选类型(Optinal)。
基础类型
Xcode从6.0开始加入了Playground代码测试,可以实时查看代码执行结果,下面使用Playground简单演示一下Swift的基础内容,对Swift有个简单的认识:
importFoundation
vara:
Int=1//通过var定义一个变量
//下面变量b虽然没有声明类型,但是会自动进行类型推断,这里b推断为Int类型
varb=2
varc:
UInt=3
letd=a+b//通过let定义一个变量
//下面通过"\()"实现了字符串和变量相加(字符串插值),等价于println("d="+String(d))
println("d=\(d)")//结果:
d=3
//注意由于Swift是强类型语言,a是Int类型而c是UInt类型,二者不能运算,下面的语句报错;但是注意如果是类似于:
leta=1+2.0是不会报错的,因为两个都是字面量,Swift会首先计算出结果再推断a的类型
//lete=a+c
//Int.max是Int类型的最大值,类似还有Int.min、Int32.max、Int32.min等
lete=Int.max//结果:
9223372036854775807
varf:
Float=1.0
varg=2.0//浮点型自动推断为Double类型
varh:
String="hello"
//emoj表情也可以作为变量或者常量,事实上所有Unicode字符都是可以的
var💖🍎="loveandapple"
//两个字符串相加,但是注意不同类型不能相加
vari=h+💖🍎//结果:
helloloveandapple
//布尔类型只有两个值true、false,类似于if语句中的条件只能是布尔类型不能像ObjC一样非0即真
varj:
Bool=true
//字符类型,同样使用双引号,但是只能是一个字符,如果不指定类型则"c"默认会推断为字符串(vark:
Character="c"是字符类型,但是vark="c"是字符串类型)
vark:
Character="c"
varl=00100//等于100,可以在前面添加额外的0
varm=10_000_000//等于10000000,可以使用增加额外的下划线方便阅读而不改变值的大小
Swift通过var进行变量定义,通过let进行常量定义(这和其他高级语言比较类似,例如F#);
Swift添加了类型推断,对于赋值的常量或者变量会自动推断其具体类型;
Swift是强类型语言(应该说它比C#、Java等强类型语言控制还要严格),不同的数据类型之间不能隐式转化,如果需要转化只能强制转化;
在Swift中类型转换直接通过其类型构造函数即可,降低了API的学习成本;
集合类型
Swift提供了三种集合类型:
数组Array、集合Set、字典Dictionary。
和ObjC不同的是,由于Swift的强类型,集合中的元素必须是同一类型,而不能像ObjC一样可以存储任何对象类型,并且注意Swift中的集合是值类型而非引用类型(事实上包括String、结构体struct、枚举enum都是值类型)。
首先看一下Swift中的数组:
//声明数组的时候必须确定其类型,下面使用[String]声明一个字符串数组([String]是Array
//vara:
Array
vara:
[String]=["hello","world"]
a[0]//访问数组元素
//下面创建一个Double类型的数组,这里没有使用字面量,当前是一个空数组,当然也可以写成varb:
[Double]=[]
varb=[Double]()
foriina{
println("i=\(i)")
}
//添加元素,Swift中可变类型不再由单独的一个类型来表示,统统使用Array,如果想声明为不可变数组只要使用let定义即可
a.append("!
")
a+=["I","am","Kenshin"]//追加元素
println("a.count=\(a.count)")//结果:
a.count=6
a[3...5]=["I","Love","Swift"]//修改元素,但是注意无法用这种方式添加元素
//a[6]=["."]//这种方式是错误的
a.insert("New",atIndex:
5)//插入元素:
helloworld!
ILoveNewSwift
a.removeAtIndex(5)//删除指定元素
//使用全局enumerate函数遍历数据索引和元素
for(index,element)inenumerate(a){
println("index=\(index),element=\(element)")
}
//使用构造函数限制数组元素个数并且指定默认值,等价于varc=Array(count:
3,repeatedValue:
1),自动推断类型
varc=[Int](count:
3,repeatedValue:
1)
Set表示没有顺序的集合:
//注意集合没有类似于数组的简化形式,例如不能写成vara:
[String]=["hello","world"]
vara:
Set
varb:
Set=[1,2]//类型推断:
Set
a.insert("!
")//注意这个插入不保证顺序
if!
a.isEmpty{//判断是否为空
a.remove("!
")
}
if!
a.contains("!
"){
a.insert("!
")
}
Dictionary字典同样是没有顺序的,并且在Swift中字典同样要在使用时明确具体的类型。
和ObjC中一样,字典必须保证key是唯一的,而这一点就要求在Swift中key必须是可哈希的,不过幸运的是Swift中的基本类型(如Int、Float、Double、Bool、String)都是可哈希的,都可以作为key。
//通过字面量进行字典初始化,注意等价于vara:
Dictionary
"success",404:
"notfound"]
vara:
[Int:
String]=[200:
"success",404:
"notfound"]
varb=[200:
"success",404:
"notfound"]//不声明类型,根据值自动推断类型
a[200]//读取字典
a[404]="cannotfound"//修改
a[500]="internalservererror"//添加
//a=[:
]//设置为空字典,等价于:
a=[Int:
String]()
forcodeina.keys{
println("code=\(code)")
}
fordescriptionina.values{
println("description=\(description)")
}
for(code,description)ina{
println("code=\(code),description=\(description)")
}
注意:
在Swift中集合的可变性不是像ObjC一样由单独的数据类型来控制的,而是通过变量和常量来控制,这一点和其他高级语言比较类似。
元组(Tuple)
在开发过程中有时候会希望临时组织一个数据类型,此时可以使用一个结构体或者类,但是由于这个类型并没有那么复杂,如果定义起来又比较麻烦,此时可以考虑使用元组。
/**
*元组的基本用法
*/
varpoint=(x:
50,y:
100)//自动推断其类型:
(Int,Int)
point.x//可以用类似于结构体的方式直接访问元素,结果:
50
point.y//结果:
100
point.0//也可以采用类似数组的方式使用下标访问,结果:
50
point.1//结果:
100
//元组也可以不指定元素名称,访问的时候只能使用下标
letframe:
(Int,Int,Int,Float)=(0,0,100,100.0)
println(frame)//结果:
(0,0,100,100.0)
//注意下面的语句是错误的,如果指定了元组的类型则无法指定元素名称
//letframe:
(Int,Int,Int,Int)=(x:
0,y:
0,width:
100,height:
100)
varsize=(width:
100,25)//仅仅给其中一个元素命名
size.width//结果:
100
size.1//结果:
25
varhttpStatus:
(Int,String)=(200,"success")//元组的元素类型并不一定相同
var(status,description)=httpStatus//一次性赋值给多个变量,此时status=200,description="success"
//接收元组的其中一个值忽略另一个值使用"_"(注意在Swift中很多情况下使用_忽略某个值或变量)
var(sta,_)=httpStatus
println("sta=\(sta)")//结果:
sta=200
/**
*元组作为函数的参数或返回值,借助元组实现了函数的多个返回值
*/
funcrequest()->(code:
Int,description:
String){
return(404,"notfound")
}
varresult=request()
result.0//结果:
404
result.1//结果:
notfound
result.code//结果:
404
result.description//结果:
notfound
可选类型
所谓可选类型就是一个变量或常量可能有值也可能没有值则设置为可选类型。
在ObjC中如果一个对象类型没有赋值,则默认为nil,同时nil类型也只能作为对象类型的默认值,对于类似于Int等基本类型则对应0这样的默认值。
由于Swift是强类型语言,如果在声明变量或常量时没有进行赋值,Swift并不会默认设置初值(这一点和其他高级语言不太一样,例如C#虽然也有可选类型,但是要求并没有那么严格)。
/**
*可选类型基础
*/
varx:
Float?
//使用?
声明成一个可选类型,如果不赋值默认为nil
x=172.0
vary:
Float=60.0
//varz=x+y//注意此句报错,因为Int和Int?
根本就是两种不同的类型,在Swift中两种不同的类型不能运算(因为不会自动进行类型转化)
varz=x!
+y//使用!
进行强制解包
varage="29"
varageInt=age.toInt()//注意ageInt是Int可选类型而不是Int类型(因为String的toInt()方法并不能保证其一定能转化为Int类型)
Swift中类似于Int和Int?
并不是同一种类型,不能进行相关运算,如果要运算只能解包;
可选类型其本质就是此类型内部存储分为“Some”和“None”两个部分,如果有值则存储到“Some”中,没有值则为“None”(早期Playground中可以看到两个部分,如今已经取消显示Some等描述了),使用感叹号强制解包的过程就是取出“Some”部分;
既然可选类型有可能有值,也可能没有值那么往往有时候就需要判断。
可以使用if直接判断一个可选类型是否为nil,这样一来就可以根据情况进行强制解包(从Some部分取出值的过程);另一个选择就是在判断的同时如果有值则将值赋值给一个临时变量或常量,否则不进入此条件语句,这个过程称之为“可选绑定”。
/**
*可选类型判断
*/
varage="29"
varageInt=age.toInt()//注意ageInt是Int可选类型而不是Int类型(因为String的toInt()方法并不能保证其一定能转化为Int类型)
ifageInt==nil{
println("ageInt=nil")
}else{
println("ageInt=\(ageInt!
)")//注意这里使用感叹号!
强制解析
}
/**
*可选类型绑定
*如果可选类型有值则将值赋值给一个临时变量或者常量(此时此变量或者常量接受的值已经不是可选类型),如果没有值则不执行此条件
*/
ifletnewAge=ageInt{//此时newAge可以定义成常量也可以定义成变量
println("newAge=\(newAge)")//注意这里并不需要对newAge强制解包
}else{
println("ageInt=nil")
}
通过前面的演示可以看出Swift中的可选绑定如果实际计算不得不进行强制解包,如果一个可选类型从第一次赋值之后就能保证有值那么使用时就不必进行强制解包了,这种情况下可以使用隐式可选解析类型(通过感叹号声明而不是问号)
/**
*隐式解析可选类型
*/
varage:
Int!
=0//通过感叹号声明隐式解析可选类型,此后使用时虽然是可选类型但是不用强制解包
age=29
varnewAge:
Int=age//不用强制解包直接赋值给Int类型(程序会自动解包)
ifvartempAge=age{
println("tempAge=\(tempAge)")
}else{
println("age=nil")
}
运算符
Swift中支持绝大多数C语言的运算符并改进以减少不必要的错误(例如等号赋值后不返回值),算术运算会检查溢出情况,必要时还能使用新增的溢出运算符。
另外Swift中还可以对浮点数使用取余运算符,新增了区间运算符。
对于基本的运算符这里不再一一介绍,简单看一下Swift中的区间运算符和溢出运算符。
/**
*区间运算符,通常用于整形或者字符范围(例如"a"..."z")
*/
foriin1...5{//闭区间运算符...(从1到5,包含5)
println("i=\(i)")
}
foriin1..<5{//半开区间运算符..<(从1到4)
println("i=\(i)")
}
varstr="helloworld."
varrange="a"..."z"
fortinstr{
ifrange.contains(String(t)){
print(t)//结果:
helloworld
}
}
/**
*溢出运算符
*/
vara=UInt8.max//a=255
//varb:
UInt8=a+1//注意b会出现溢出,此句报错
//下面使用溢出运算符,结果为:
0,类似的还有&-、&*、&/
//使用溢出运算符可以在最大值和最小值之前循环而不会报错
varb:
UInt8=a&+1
溢出运算符的原理其实很简单,例如对于UInt8,如果8位均为1则十进制表示是255,但是当加1之后则变成了9位“100000000”,出现了溢出但是UInt8本身值只能存储8位,所以取后面8位就变成了“00000000”,十进制表示就是0。
控制流
Swift中的多数控制流和其他语言差别并不大,例如for、while、dowhile、if、switch等,而且有些前面已经使用过(例如forin循环),这里将着重介绍一些不同点。
vara=["a","b","c","d","e","f","g"]
letb=a[1]
/**
*switch支持一个case多个模式匹配,同时case后不用写break也会在匹配到种情况后自动跳出匹配,不存在隐式贯穿,如果想要贯穿在case之后添加"fallthrough"关键字
*/
switchb{
case"a","b":
println("b=aorb=b")
case"c","d","e","f":
println("bin(c,d,e,f)")
default:
println("b=g")
}
/**
*匹配区间,同时注意switch必须匹配所有情况,否则必须加上default
*/
letc:
Int=88
switchc{
case1...60:
println("1-60")
case61...90:
println("61-90")
case91...100:
println("91-100")
default:
println("1>c>100")
}
/**
*元组匹配、值绑定、where条件匹配
*注意下面的匹配没有default,因为它包含了所有情况
*/
vard=(x:
900,y:
0)
switchd{
case(0,0):
println("din(0,0)")
case(_,0):
//忽略x值匹配
println("diny")
case(0,lety):
//值绑定
println("dinx,y=\(y)")
case(-100...100,-100...100):
//注意这里有可能和第一、二、三个条件重合,但是Swift允许多个case匹配同一个条件,但是只会执行第一个匹配
println("xin(0-100),yin(0-100)")
caselet(x,y)wherex==y:
//where条件匹配,注意这里的写法等同于:
(letx,lety)wherex==y
println("x=y=\(x)")
caselet(x,y):
println("x=\(x),y=\(y)")
}
在其他语言中通常可以使用break、continue、return(Swift中添加了fallthrough)等来终止或者跳出某个执行语句,但是对于其行为往往是具有固定性的,例如break只能终止其所在的内层循环,而return只能跳出它所在的函数。
在Swift中这种控制转移功能得到了加强,那就是使用标签。
利用标签你可以随意指定转移的位置,例如下面的代码演示了如何直接通过标签跳出最外层循环:
vara=5
whileLoop:
while--a>0{
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- iOS 开发 系列 Swift 语言 总结