基础类型
- Swift通过var进行变量定义,通过let进行常量定义
Swift添加了类型推断,对于赋值的常量或者变量会自动推断其具体类型;
Swift是强类型语言(应该说它比C#、Java等强类型语言控制还要严格),不同的数据类型之间不能隐式转化,如果需要转化只能强制转化;
-
在Swift中类型转换直接通过其类型构造函数即可,降低了API的学习成本
let a :Int = 1 let b = 2 var c :Float = 1.0 var d = "hello" var e = "guagua" var g = d + e //hello guagua
集合类型
数组Array、集合Set、字典Dictionary。和ObjC不同的是,由于Swift的强类型,集合中的元素必须是同一类型,而不能像ObjC一样可以存储任何对象类型,并且注意Swift中的集合是值类型而非引用类型(事实上包括String、结构体struct、枚举enum都是值类型)。
var a:[String]=["hello","world"]
a[0] //访问数组元素
var b:[Double]=[] 等价于var b=[Double]()
a.append("!")
a+=["I" ,"am" ,"Kenshin"] //追加元素
a[3...5]=["I","Love","Swift"] //修改元素,但是注意无法用这种方式添加元素
a.insert("New", atIndex: 5) //插入元素:hello world! I Love New Swift
a.removeAtIndex(5) //删除指定元素
//使用构造函数限制数组元素个数并且指定默认值,等价于var c=Array(count: 3, repeatedValue: 1),自动推断类型
var c=[Int](count: 3, repeatedValue: 1)
Dictionary字典同样是没有顺序的,并且在Swift中字典同样要在使用时明确具体的类型。和ObjC中一样,字典必须保证key是唯一的,而这一点就要求在Swift中key必须是可哈希的,不过幸运的是Swift中的基本类型(如Int、Float、Double、Bool、String)都是可哈希的,都可以作为key。
var a:[Int:String]=[200:"success",404:"not found"]
var b=[200:"success",404:"not found"] //不声明类型,根据值自动推断类型
a[200] //读取字典
a[404]="can not found" //修改
a[500]="internal server error" //添加
//a=[:] //设置为空字典,等价于:a=[Int:String]()
元组(Tuple)
在开发过程中有时候会希望临时组织一个数据类型,此时可以使用一个结构体或者类,但是由于这个类型并没有那么复杂,如果定义起来又比较麻烦,此时可以考虑使用元组。
- 类似数组可以通过下标取值,指定元素名称还可通过名称取值
var point=(x:50,y:100) //自动推断其类型:(Int,Int)
point.x //可以用类似于结构体的方式直接访问元素,结果:50
point.y //结果:100
point.0 //也可以采用类似数组的方式使用下标访问,结果:50
point.1 //结果:100
- 元组作为函数的参数或返回值,借助元组实现了函数的多个返回值
func request()->(code:Int,description:String){
return (404,"not found")
}
var result=request()
result.0 //结果:404
result.1 //结果:not found
result.code //结果:404
result.description //结果:not found
//接收元组的其中一个值忽略另一个值使用"_"(注意在Swift中很多情况下使用_忽略某个值或变量)
var (sta,_)=result //sta = 404
可选类型
所谓可选类型就是一个变量或常量可能有值也可能没有值则设置为可选类型。在ObjC中如果一个对象类型没有赋值,则默认为nil,同时nil类型也只能作为对象类型的默认值,对于类似于Int等基本类型则对应0这样的默认值。由于Swift是强类型语言,如果在声明变量或常量时没有进行赋值,Swift并不会默认设置初值(这一点和其他高级语言不太一样,例如C#虽然也有可选类型,但是要求并没有那么严格)。
var x:Float? //使用?声明成一个可选类型,如果不赋值默认为nil
var z=x!+y //使用!进行强制解包
Swift中类似于Int和Int?并不是同一种类型,不能进行相关运算,如果要运算只能解包;
可选项判断的两种方式
if ageInt==nil {
println("ageInt=nil")
}else{
println("ageInt=\(ageInt!)") //注意这里使用感叹号!强制解析
}
/**
* 可选类型绑定
* 如果可选类型有值则将值赋值给一个临时变量或者常量(此时此变量或者常量接受的值已经不是可选类型),如果没有值则不执行此条件
*/
if let newAge=ageInt{ //此时newAge可以定义成常量也可以定义成变量
println("newAge=\(newAge)") //注意这里并不需要对newAge强制解包
}else{
println("ageInt=nil")
}
运算符
Swift中支持绝大多数C语言的运算符并改进以减少不必要的错误(例如等号赋值后不返回值),算术运算会检查溢出情况,必要时还能使用新增的溢出运算符。另外Swift中还可以对浮点数使用取余运算符,新增了区间运算符。对于基本的运算符这里不再一一介绍,简单看一下Swift中的区间运算符和溢出运算符。
/**
* 区间运算符,通常用于整形或者字符范围(例如"a"..."z")
*/
for i in 1...5 { //闭区间运算符...(从1到5,包含5)
println("i=\(i)")
}
for i in 1..<5{ //半开区间运算符..<(从1到4)
println("i=\(i)")
}
var str = "hello world."
var range="a"..."z"
for t in str {
if range.contains(String(t)) {
print(t) //结果:helloworld
}
}
/**
* 溢出运算符
*/
var a=UInt8.max //a=255
//var b:UInt8=a+1 //注意b会出现溢出,此句报错
//下面使用溢出运算符,结果为:0,类似的还有&-、&*、&/
//使用溢出运算符可以在最大值和最小值之前循环而不会报错
var b:UInt8=a &+ 1
控制流
Swift中的多数控制流和其他语言差别并不大,例如for、while、do while、if、switch等,而且有些前面已经使用过(例如for in循环),这里将着重介绍一些不同点。
switch支持一个case多个模式匹配,同时case后不用写break也会在匹配到种情况后自动跳出匹配,不存在隐式贯穿,如果想要贯穿在case之后添加"fallthrough"关键字
switch b{
case "a","b":
println("b=a or b=b")
case "c","d","e","f":
println("b in (c,d,e,f)")
default:
println("b=g")
}
匹配区间,同时注意switch必须匹配所有情况,否则必须加上default
let c:Int=88
switch c{
case 1...60:
println("1-60")
case 61...90:
println("61-90")
case 91...100:
println("91-100")
default:
println("1>c>100")
}
- 元组匹配、值绑定、where条件匹配
- 注意下面的匹配没有default,因为它包含了所有情况
var d=(x:900,y:0)
switch d{
case (0,0):
println("d in (0,0)")
case (_,0): //忽略x值匹配
println("d in y")
case (0,let y)://值绑定
println("d in x,y=\(y)")
case (-100...100,-100...100): //注意这里有可能和第一、二、三个条件重合,但是Swift允许多个case匹配同一个条件,但是只会执行第一个匹配
println("x in(0-100),y in (0-100)")
case let (x,y) where x==y: //where条件匹配,注意这里的写法等同于:(let x,let y) where x==y
println("x=y=\(x)")
case let (x, y):
println("x=\(x),y=\(y)")
在其他语言中通常可以使用break、continue、return(Swift中添加了fallthrough)等来终止或者跳出某个执行语句,但是对于其行为往往是具有固定性的,例如break只能终止其所在的内层循环,而return只能跳出它所在的函数。在Swift中这种控制转移功能得到了加强,那就是使用标签。利用标签你可以随意指定转移的位置,例如下面的代码演示了如何直接通过标签跳出最外层循环:
var a=5
whileLoop:
while --a>0 {
for var i=0;i<a;++i{
println("a=\(a),i=\(i)")
break whileLoop
//如果此处直接使用break将跳出for循环,而由于这里使用标签直接跳出了while,结果只会打印一次,其结果为:a=4,i=0
}
}