• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

[转]iOS开发系列--Swift语言

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

Swift是苹果2014年推出的全新的编程语言,它继承了C语言、ObjC的特性,且克服了C语言的兼容性问题。Swift发展过程中不仅保留了ObjC很多语法特性,它也借鉴了多种现代化语言的特点,在其中你可以看到C#、Java、Javascript、Python等多种语言的影子。同时在2015年的WWDC上苹果还宣布Swift的新版本Swift2.0,并宣布稍后Swift即将开源,除了支持iOS、OS X之外还将支持linux。

本文将继续iOS开发系列教程,假设读者已经有了其他语言基础(强烈建议初学者从本系列第一章开始阅读,如果您希望从Swift学起,那么推荐你首先阅读苹果官方电子书《the swift programming language》),不会从零基础一点点剖析这门语言的语法,旨在帮助大家快速从ObjC快速过度到Swift开发中。即便如此,要尽可能全面的介绍Swift的语法特点也不是一件容易的事情,因此本文将采用较长的篇幅进行介绍。

  1. 基础部分
    1. 第一个Swift程序
    2. 数据类型
      1. 基础类型
      2. 集合类型
      3. 元组
      4. 可选类型
    3. 运算符
    4. 控制流
  2. 函数和闭包
    1. 函数
    2. 闭包
    1. 属性
    2. 方法
    3. 下标脚本
    4. 继承
  3. 协议
  4. 扩展
  5. 枚举和结构体
    1. 结构体
    2. 枚举
  6. 泛型
  7. 目 录

基础部分

第一个Swift程序

创建一个命令行程序如下:

1
2
3
4
5
6
import Foundation
 
/**
*  Swift没有main函数,默认从top level code的上方开始自上而下执行(因此不能有多个top level代码)
*/
println("Hello, World!")

从上面的代码可以看出:

  1. Swift没有main函数,从top level code的上方开始往下执行(就是第一个非声明语句开始执行[表达式或者控制结构,类、结构体、枚举和方法等属于声明语句]),不能存在多个top level code文件(否则编译器无法确定执行入口,事实上swift隐含一个main函数,这个main函数会设置并调用全局 “C_ARGC C_ARGV”并调用由top level code构成的top_level_code()函数);
  2. Swift通过import引入其他类库(和Java比较像);
  3. 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有个简单的认识:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import Foundation
 
var a:Int=1 //通过var定义一个变量
 
//下面变量b虽然没有声明类型,但是会自动进行类型推断,这里b推断为Int类型
var b=2
 
var c:UInt=3
let d=a+b //通过let定义一个变量
 
//下面通过"\()"实现了字符串和变量相加(字符串插值),等价于println("d="+String(d))
println("d=\(d)"//结果:d=3
 
//注意由于Swift是强类型语言,a是Int类型而c是UInt类型,二者不能运算,下面的语句报错;但是注意如果是类似于:let a=1+2.0是不会报错的,因为两个都是字面量,Swift会首先计算出结果再推断a的类型
//let e=a+c
 
//Int.max是Int类型的最大值,类似还有Int.min、Int32.max、Int32.min等
let e=Int.max //结果:9223372036854775807
 
var f:Float=1.0
var g=2.0 //浮点型自动推断为Double类型
 
var h:String="hello "
 
//emoj表情也可以作为变量或者常量,事实上所有Unicode字符都是可以的
var ????????="love and apple"
 
//两个字符串相加,但是注意不同类型不能相加
var i=h+???????? //结果:hello love and apple
 
//布尔类型只有两个值true、false,类似于if语句中的条件只能是布尔类型不能像ObjC一样非0即真
var j:Bool=true
 
//字符类型,同样使用双引号,但是只能是一个字符,如果不指定类型则"c"默认会推断为字符串(var k:Character="c"是字符类型,但是var k="c"是字符串类型)
var k:Character="c"
 
var l=00100 //等于100,可以在前面添加额外的0
var m=10_000_000 //等于10000000,可以使用增加额外的下划线方便阅读而不改变值的大小
  1. Swift通过var进行变量定义,通过let进行常量定义(这和其他高级语言比较类似,例如F#);
  2. Swift添加了类型推断,对于赋值的常量或者变量会自动推断其具体类型;
  3. Swift是强类型语言(应该说它比C#、Java等强类型语言控制还要严格),不同的数据类型之间不能隐式转化,如果需要转化只能强制转化;
  4. 在Swift中类型转换直接通过其类型构造函数即可,降低了API的学习成本;

集合类型

Swift提供了三种集合类型:数组Array、集合Set、字典Dictionary。和ObjC不同的是,由于Swift的强类型,集合中的元素必须是同一类型,而不能像ObjC一样可以存储任何对象类型,并且注意Swift中的集合是值类型而非引用类型(事实上包括String、结构体struct、枚举enum都是值类型)。

首先看一下Swift中的数组:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
//声明数组的时候必须确定其类型,下面使用[String]声明一个字符串数组([String]是Array<String>简单表达形式)
//var a:Array<String>=["hello","world"]
var a:[String]=["hello","world"]
a[0//访问数组元素
 
//下面创建一个Double类型的数组,这里没有使用字面量,当前是一个空数组,当然也可以写成var b:[Double]=[]
var b=[Double]()
 
for i in a{
    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"atIndex5//插入元素:hello world! I Love New Swift
 
a.removeAtIndex(5//删除指定元素
 
//使用全局enumerate函数遍历数据索引和元素
for (index,elementin enumerate(a){
    println("index=\(index),element=\(element)")
}
 
//使用构造函数限制数组元素个数并且指定默认值,等价于var c=Array(count: 3, repeatedValue: 1),自动推断类型
var c=[Int](count3repeatedValue1)

Set表示没有顺序的集合:

1
2
3
4
5
6
7
8
9
10
11
12
13
//注意集合没有类似于数组的简化形式,例如不能写成var a:[String]=["hello","world"]
var a:Set<String>=["hello","world"]
var b:Set=[1,2//类型推断:Set<Int>
 
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。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
//通过字面量进行字典初始化,注意等价于var a:Dictionary<Int,String>=[200:"success",404:"not found"]
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]()
 
for code in a.keys{
    println("code=\(code)")
}
 
for description in a.values{
    println("description=\(description)")
}
 
for (code,descriptionin a{
    println("code=\(code),description=\(description)")
}

注意:在Swift中集合的可变性不是像ObjC一样由单独的数据类型来控制的,而是通过变量和常量来控制,这一点和其他高级语言比较类似。

元组(Tuple)

在开发过程中有时候会希望临时组织一个数据类型,此时可以使用一个结构体或者类,但是由于这个类型并没有那么复杂,如果定义起来又比较麻烦,此时可以考虑使用元组。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
/**
 * 元组的基本用法
 */
var point=(x:50,y:100//自动推断其类型:(Int,Int)
point.x //可以用类似于结构体的方式直接访问元素,结果:50
point.y //结果:100
point.0 //也可以采用类似数组的方式使用下标访问,结果:50
point.1 //结果:100
 
//元组也可以不指定元素名称,访问的时候只能使用下标
let frame:(Int,Int,Int,Float)=(0,0,100,100.0)
println(frame//结果:(0, 0, 100, 100.0)
 
//注意下面的语句是错误的,如果指定了元组的类型则无法指定元素名称
//let frame:(Int,Int,Int,Int)=(x:0,y:0,width:100,height:100)
 
 
var size=(width:100,25//仅仅给其中一个元素命名
size.width //结果:100
size.1 //结果:25
 
 
var httpStatus:(Int,String)=(200,"success"//元组的元素类型并不一定相同
 
var (status,description)=httpStatus //一次性赋值给多个变量,此时status=200,description="success"
 
//接收元组的其中一个值忽略另一个值使用"_"(注意在Swift中很多情况下使用_忽略某个值或变量)
var (sta,_)=httpStatus
println("sta=\(sta)"//结果:sta=200
 
/**
 * 元组作为函数的参数或返回值,借助元组实现了函数的多个返回值
 */
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

可选类型

所谓可选类型就是一个变量或常量可能有值也可能没有值则设置为可选类型。在ObjC中如果一个对象类型没有赋值,则默认为nil,同时nil类型也只能作为对象类型的默认值,对于类似于Int等基本类型则对应0这样的默认值。由于Swift是强类型语言,如果在声明变量或常量时没有进行赋值,Swift并不会默认设置初值(这一点和其他高级语言不太一样,例如C#虽然也有可选类型,但是要求并没有那么严格)。

1
2
3
4
5
6
7
8
9
10
11
12
13
/**
 * 可选类型基础
 */
var x:Float//使用?声明成一个可选类型,如果不赋值默认为nil
x=172.0
 
var y:Float=60.0
 
//var z=x+y //注意此句报错,因为Int和Int?根本就是两种不同的类型,在Swift中两种不同的类型不能运算(因为不会自动进行类型转化)
var z=x!+y //使用!进行强制解包
 
var age="29"
var ageInt=age.toInt() //注意ageInt是Int可选类型而不是Int类型(因为String的toInt()方法并不能保证其一定能转化为Int类型)
  1. Swift中类似于Int和Int?并不是同一种类型,不能进行相关运算,如果要运算只能解包;
  2. 可选类型其本质就是此类型内部存储分为“Some”和“None”两个部分,如果有值则存储到“Some”中,没有值则为“None”(早期Playground中可以看到两个部分,如今已经取消显示Some等描述了),使用感叹号强制解包的过程就是取出“Some”部分;

既然可选类型有可能有值,也可能没有值那么往往有时候就需要判断。可以使用if直接判断一个可选类型是否为nil,这样一来就可以根据情况进行强制解包(从Some部分取出值的过程);另一个选择就是在判断的同时如果有值则将值赋值给一个临时变量或常量,否则不进入此条件语句,这个过程称之为“可选绑定”。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* 可选类型判断
*/
var age="29"
var ageInt=age.toInt() //注意ageInt是Int可选类型而不是Int类型(因为String的toInt()方法并不能保证其一定能转化为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中的可选绑定如果实际计算不得不进行强制解包,如果一个可选类型从第一次赋值之后就能保证有值那么使用时就不必进行强制解包了,这种情况下可以使用隐式可选解析类型(通过感叹号声明而不是问号)

1
2
3
4
5
6
7
8
9
10
11
12
/**
* 隐式解析可选类型
*/
var age:Int!=0 //通过感叹号声明隐式解析可选类型,此后使用时虽然是可选类型但是不用强制解包
age=29
var newAge:Int=age //不用强制解包直接赋值给Int类型(程序会自动解包)
 
if var tempAge=age {
    println("tempAge=\(tempAge)")
}else{
    println("age=nil")
}

运算符

Swift中支持绝大多数C语言的运算符并改进以减少不必要的错误(例如等号赋值后不返回值),算术运算会检查溢出情况,必要时还能使用新增的溢出运算符。另外Swift中还可以对浮点数使用取余运算符,新增了区间运算符。对于基本的运算符这里不再一一介绍,简单看一下Swift中的区间运算符和溢出运算符。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
/**
 * 区间运算符,通常用于整形或者字符范围(例如"a"..."z")
 */
for i in 1...5 //闭区间运算符...(从1到5,包含5)
    println("i=\(i)")
}<

鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
swift:Optional Type 、Swift和Objective-C混编的讲解发布时间:2022-07-13
下一篇:
学习 swift (1)发布时间:2022-07-13
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap