0.1 关于Swift(About Swift)
用途:编写IOS
、OS X
、watchOS
应用程序
特点归纳:
- 基于
Cocoa
和Cocoa Touch
框架 - 自动垃圾回收(自动引用计数)
- 采用了
Object-C
的命名参数和动态对象模型,兼容Object-C
,可以无缝对接到现有的Cocoa
框架 - 支持
过程式编程
和面向对象编程
- 支持代码预览(像脚本语言一样,可以实时查看结果)
0.2 Swift初见(A Swift Tour)
0.2.1 简单值(Simple Values)
0.2.1.1 自动推断类型
说明:声明的同时赋值的话,如果不指定类型,编译器会自动推断其类型。
1 | // 自动推断类型为integer |
0.2.1.2 指定类型
说明:指定类型会导致强制类型转换
1 | // 指定类型为double |
0.2.1.3 显示转换(在表达式中)
说明:表达式中的值任何时候都不会发生隐式转化。需要转换为其它类型必须进行显示转换。
特别:\(变量或表达式)
(转换成字符串类型)
1 | // string |
\(变量或表达式)
1 | let apples = 3 |
0.2.1.4 数组和字典
声明并初始化(自动推断类型)
1 | // 数组 |
空数组和空字典
1 | // 空数组(指定每个元素的类型) |
0.2.2 控制流(Control Flow)
0.2.2.1 条件判断
说明:有两类
- if
- switch
if语法:
- 包裹条件的
()
可以省略 - 语句的
{}
不可以省略 条件
必须是一个布尔表达式
(其它数据类型会报错,因为不会隐式转换)
switch语法:
- 支持任意类型(不仅仅是整数)
- 支持各种比较操作(不仅仅是测试想等)
case
后可以有多个数据case
后可以使用where
字句- 匹配字句后程序会退出
switch
,不需要在每个字句结尾写break - …
技巧:if
和let
组合起来使用可以来为可选值解包
if(配合let解包可选值)
1 | var optionalString:String? = "Hello" |
switch
1 | let vegetable = "red pepper" |
0.2.2.2 循环
说明:有4类
- for-in
- for
- while
- repeat-while
for-in
1 | // 寻找字典中的所有数组中的最大值 |
repeat-while
1 | var n = 2 |
for
区间:
- 包含边界:
...
- 不包含上边界:
..<
1 | // 区间的方式 |
0.2.3 函数和闭包(Functions and Closures)
0.2.3.1 简单函数
1 | func greet(name: String, day: String) -> String { |
0.2.3.2 返回元组
1 | // 找到元组的最大值、最小值和总和 |
0.2.3.3 可变参数
1 | // 可变参数函数 |
0.2.3.4 函数嵌套
说明:如果嵌套的函数被返回,调用返回的函数就会出现闭包的效果。
1 | // 函数嵌套 |
0.2.3.5 返回函数
说明:返回的函数是闭包的一种
1 | // 返回函数 |
0.2.3.6 函数作为参数
1 | // 使用函数作为参数 |
0.2.3.7 匿名函数(匿名闭包)
说明:匿名函数写法非常自由
- 如果一个闭包的类型已知,比如作为一个回调函数,可以忽略参数的类型和返回值
- 单个语句闭包会把它语句的值当作结果返回
- 可以通过参数位置而不是参数名引用参数
- 当一个闭包作为最后一个参数传给一个函数的时候,它可以直接跟在括号后面
- 当一个闭包是传给函数的唯一参数,可以完全忽略
()
1 | // 匿名闭包1(包含参数类型和返回值类型) |
0.2.4 对象和类(Object and Classes)
语法:
class 类型名 {...}
- 使用
.
访问实例的属性和方法 - 在成员方法中使用
self
引用当前实例对象 - 使用构造函数
init
初始化类实例 - 使用析构函数
deinit
在删除对象之前做一些清理工作 - 没有标准的根类(不同于
java
) - 子类的定义:
class 子类名:父类名
- 重写父类的方法许必须用
override
标记
简单类
1 | // 形状 |
构造函数和子类
1 | // 带名字的形状(基类) |
0.2.4.1 计算属性
说明:计算属性有getter和setter
- get:读取属性时返回计算出的属性值
- set:写入值时被调用,其中内置变量
newValue
存储新值
1 | // 等腰三角形(子类) |
0.2.4.2 属性监控
说明:不需要计算属性,但是仍然需要在设置一个新值之前或者之后运行代码。可以使用willset
和didSet
。
- willset:在设置之前调用
- didSet:在设置后后调用
1 | // 包含一个三角形实例和一个正方形实例作为成员,并确保边长相等 |
0.2.4.3 实例是可选值
说明:当实例是nil是,需要避免访问实例的成员导致报错。
1 | // 声明可选型 |
0.2.5 枚举和结构体(Enumerations and Structures)
0.2.5.1 枚举
关键字:enum
说明:swift中的所有命名类型都可以包含方法(包括枚举)。
- 可以不设置枚举值的原始值类型
- 同一枚举类型的实例的成员(枚举值)的原始值(可以在创建实例的时候传入值)可以不同
- 如果原始值类型为
Int
,可以只设置第一个原始值,剩下的原始值会按照顺序自动完成赋值 - 也可以使用字符串或者浮点数作为枚举的原始值
- 使用
rawValue
属性来访问一个枚举成员的原始值 - 存在一个默认的初始化构造器
init?(rawValue:)
,这意味着可以通过原始值创建可选型美剧值(使用前需要解包) - 声明枚举类型常量或在
switch
中时,当指定了枚举类型时,可以使用.枚举值
的方式
1 | // 扑克牌级别 |
不设置原始值类型
1 | // 扑克牌花色 |
枚举的每个case还可以包含一些值
1 | // 服务器响应 |
0.2.5.2 结构体
说明:结构体和类有很多相同的地方,比如方法和构造器。它们之间最大的区别就是结构体是传值,类是传引用。
1 | // 扑克牌 |
0.2.6 协议和扩展(Protocols and Extensions)
0.2.6.1 协议
关键字:protocol
说明:类似于接句,类、枚举、结构体都可以实现协议。
注意:
- 使用结构体实现协议时,如果实现的方法会修改结构体,需要用
mutating
标记。 - 可以直接使用协议声明变量或常量,但无法调用运行时类型实现的协议值完的方法或属性
1 | // 定义一个协议 |
1 | // 通过类实现这个协议 |
1 | // 通过结构体实现这个协议 |
0.2.6.2 扩展
关键字:extension
描述:为现有的类型添加功能,比如新的方法和计算属性。
说明:你可以使用扩展在别处修改定义,甚至是从外部库活着框架引入的一个类型,使得这个类型遵循某个协议。
1 | // 扩展 |
0.2.7 范型(Generics)
描述:在<>
中写一个名字来创建一个范型函数或者类型。
说明:可以应用于
- 函数
- 方法
- 类
- 枚举
- 结构体
特点:
- 可以使用
where
来指定对类型的要求 <T: Equatable>
和<T where T: Equatable>
等价
1 | func anyCommonElements <T: SequenceType, U: SequenceType where T.Generator.Element: Equatable, T.Generator.Element == U.Generator.Element> (lhs: T, _ rhs: U) -> Bool { |