cnswift.org-关于 Swift.pdf
cnswift.org-版本兼容性.pdf
cnswift.org-Swift 概览.pdf
cnswift.org-基础内容.pdf
cnswift.org-基本运算符.pdf
cnswift.org-字符串和字符.pdf
cnswift.org-集合类型.pdf
cnswift.org-控制流.pdf
cnswift.org-函数.pdf
cnswift.org-闭包.pdf
cnswift.org-枚举.pdf
cnswift.org-类和结构体.pdf
cnswift.org-属性.pdf
cnswift.org-方法.pdf
cnswift.org-下标.pdf
cnswift.org-继承.pdf
cnswift.org-初始化.pdf
cnswift.org-反初始化.pdf
cnswift.org-可选链.pdf
cnswift.org-错误处理.pdf
cnswift.org-类型转换.pdf
cnswift.org-内嵌类型.pdf
cnswift.org-扩展.pdf
cnswift.org-协议.pdf
cnswift.org-泛型.pdf
cnswift.org-不透明类型.pdf
cnswift.org-自动引用计数.pdf
cnswift.org-内存安全性.pdf
cnswift.org-访问控制.pdf
cnswift.org-高级运算符.pdf
cnswift.org-关于语言参考.pdf
cnswift.org-词汇结构.pdf
cnswift.org-类型.pdf
cnswift.org-表达式.pdf
cnswift.org-特性.pdf
cnswift.org-文档修订历史.pdf
cnswift.org/about-swift
关于 Swift
Swift 是编写程序的绝佳选择,⽆论是⼿机、电脑还是服务器,任何能跑代码的设备都是如此。它
是⼀门集现代语⾔之⼤成,集结了苹果的⼯程师⽂化精髓以及开源社区多样化于⼀⾝的编程语
⾔。编译器为专为性能所调优,语⾔专为开发所优化,⼆者绝不互相妥协。
Swift 语⾔还对新的程序员⼗分友好。它是第⼀个⼯业级系统编程语⾔,却⼜像脚本语⾔那样富有
张⼒且⼗分有趣。在 Playground 编写代码并实时查看 Swift 代码运算结果,完全不需要从头编译
然后运⾏软件。
Swift 通过向其他现代编程模式学习,定义了⼤量类来避免常⻅的编程错误:
变量⼀定是在使⽤前初始化的;
数组索引会检查越界错误;
整数会检查溢出;
可选项保证了 nil 值会显式处理;
内存⾃动管理;
错误处理允许从意外错误中恢复控制。
Swift 代码为⼤部分现代硬件编译和优化。语法和基本库都基于指导原则设计,这显然也是你让代
码的最佳⽅式。这使得集安全和速度于⼀⾝的 Swift 适⽤于任何场景,从编写 “Hello, world!”到整
个操作系统,都是上上之选。
Swift ⽤轻量级的语法集合强⼤的类型接⼝和模式匹配,能够把复杂的想法以简洁优雅的形式表
达。得益于此,代码不仅仅更好写了,还变得更加易读和益于优化。
Swift 已经投放市场多年,它还会继续演进,带来更多的新特性和新功能。我们对 Swift 语⾔充满
了信⼼,我们期待着你⽤ Swift 进⾏创作!
1/1
cnswift.org/version-compatibility
版本兼容性
这本书讲述的是 Swift 5.1,它是 Xcode 11 中包含的默认版本。你可以使⽤ Xcode 11 来编译⽤
Swift 5.1、Swift 4.2 或 Swift 4 写的代码。
当你使⽤ Xcode 11 编译 Swift 4 和 Swift 4.2 代码时,⼤部分 Swift 5.1 的功能是可⽤的。也就是
说,下⾯的变更仅对 Swift 5.1 或后续版本⽣效:
返回不透明类型的函数需要 Swift 5.1 运⾏时;
try? 表达式并不会为已经返回的可选项引⼊额外的可选性层级;
巨⼤的整数字⾯量初始化表达式会被推断为正确的整数类型。⽐如说,
UInt64(0xffff_ffff_ffff_ffff) 会被处理成正确的值⽽不是溢出。
⽤ Swift 5.1 编写的⽬标可以依赖⽤ Swift 4.2 或 Swift 4 编写的⽬标,反之亦然。也就是说,如果
你有⼀个巨⼤的分成好多个 framework 的项⽬,你可以每次只把⼀个 framework 从 Swift 4 迁移
到 Swift 5.1.
1/1
Swift 概览
依照传统,使⽤新语⾔写的第⼀个程序都应该是在屏幕上打印“Hello,world!”,使⽤ Swift 语⾔,
你可以在⼀⾏中完成。
cnswift.org/a-swift-tour
1 print("Hello, world!")
如果你曾使⽤ C 或者 Objective-C 写代码,那么 Swift 的语法不会让你感到陌⽣——在 Swift 语⾔
当中,这⼀⾏代码就是⼀个完整的程序!你不需要为每⼀个功能导⼊单独的库⽐如输⼊输出和字
符串处理功能。写在全局范围的代码已被⽤来作为程序的⼊⼝,所以你不再需要 main()函数。同
样,你也不再需要在每句代码后边写分号。
通过向你展⽰各种编程任务,这个概览会给你⾜够的信息来开始使⽤ Swift 进⾏开发。如果觉得这
个概览不够详细,不要担⼼——这个概览所介绍的内容都会在本书的余下章节⾥进⾏详细解释。
为了更好的阅读体验,我们推荐你使用 Xcode 里的 Playground 打开本章内容,Playground
允许你编辑代码并立即看到代码的运算结果。
下载本章的 Playground (官网链接)
简单值
使⽤ let来声明⼀个常量,⽤ var来声明⼀个变量。常量的值在编译时并不要求已知,但是你必须
为其赋值⼀次。这意味着你可以使⽤常量来给⼀个值命名,然后⼀次定义多次使⽤。
1
2
3
var myVariable = 42
myVariable = 50
let myConstant = 42
常量或者变量必须拥有和你赋给它们的值相同的类型。不过,你并不需要总是显式地写出类型。
在声明⼀个常量或者变量的时候直接给它们赋值就可以让编译器推断它们的类型。⽐如上⾯的例
⼦,编译器就会推断 myVariable是⼀个整型,因为它的初始值是⼀个整型。
如果初始值并不能提供⾜够的信息(或者根本没有提供初始值),就需要在变量的后边写出来
了,⽤冒号分隔。
1
2
3
let implicitInteger = 70
let implicitDouble = 70.0
let explicitDouble: Double = 70
1/20
实验实验
创建一个常量并显式声明类型为 Float ,赋值为 4
值绝对不会隐式地转换为其他类型。如果你需要将⼀个值转换为不同的类型,需要使⽤对应的类
型显⽰地声明。
1
2
3
let label = "The width is "
let width = 94
let widthLabel = label + String(width)
实验实验
试试去掉最后一行的转换标记 String ,看看会有怎样的报错?
其实还有⼀种更简单的⽅法来把值加⼊字符串:将值写在圆括号⾥,然后再在圆括号的前边写⼀
个反斜杠 ( \) ,举个例⼦:
1
2
3
4
let apples = 3
let oranges = 5
let appleSummary = "I have \(apples) apples."
let fruitSummary = "I have \(apples + oranges) pieces of fruit."
实验实验
使用 \() 来把一个浮点计算包含进字符串,然后再在一个欢迎语句中插入某人的名字。
为字符串使⽤三个双引号( """ )来⼀次输⼊多⾏内容。只要每⼀⾏的缩进与末尾的引号相同,这
些缩进都会被移除。⽐如说:
1
2
3
4
let quotation = """
I said "I have \(apples) apples."
And then I said " I have \(apples + oranges) pieces of fruit."
"""
使⽤⽅括号( [])来创建数组或者字典,并且使⽤⽅括号来按照序号或者键访问它们的元素。
var shoppingList = ["catfish", "water", "tulips", "blue paint"]
shoppingList[1] = "bottle of water"
var occupations = [
"Malcolm": "Captain",
"Kaylee": "Mechanic",
]
occupations["Jayne"] = "Public Relations"
1
2
3
4
5
6
7
8
2/20
使⽤初始化器语法来创建⼀个空的数组或者字典。
1
2
let emptyArray = [String]()
let emptyDictionary = [String: Float]()
如果类型信息能被推断,那么你就可以⽤[]来表⽰空数组,⽤[:]来表⽰空字典。举个栗⼦,当你给
变量设置新的值或者传参数给函数的时候。
1
2
shoppingList = []
occupations = [:]
控制流
使⽤ if和 switch来做逻辑判断,使⽤ for-in, for , while,以及 repeat-while来做循环。使⽤
圆括号把条件或者循环变量括起来不再是强制的了,不过仍旧需要使⽤花括号来括住代码块。
1
2
3
4
5
6
7
8
9
10
let individualScores = [75, 43, 103, 87, 12]
var teamScore = 0
for score in individualScores {
if score > 50 {
teamScore += 3
} else {
teamScore += 1
}
}
print(teamScore)
在⼀个 if语句当中,条件必须是布尔表达式——这意味着⽐如说 if score {...}将会报错,不再隐式
地与零做计算了。
你可以⼀起使⽤ if和 let来操作那些可能会丢失的值。这些值使⽤可选项表⽰。可选的值包括了⼀
个值或者⼀个 nil来表⽰值不存在。在⼀个值的类型后边使⽤问号( ?)来把某个值标记为可选
的。
var optionalString: String? = "Hello"
print(optionalString == nil)
var optionalName: String? = "John Appleseed"
var greeting = "Hello!"
if let name = optionalName {
greeting = "Hello, \(name)"
}
1
2
3
4
5
6
7
8
3/20
实验实验
把 optionalName的值改为 nil。你得到的 greeting 是什么内容?添加 else分句,如果
optionalName为 nil就设置不同的内容给 greeting。
如果可选项的值为 nil,则条件为 false并且花括号⾥的代码将会被跳过。否则,可选项的值就会被
展开且赋给 let后边声明的常量,这样会让展开的值对花括号内的代码可⽤。
另⼀种处理可选值的⽅法是使⽤ ?? 运算符提供默认值。如果可选值丢失,默认值就会使⽤。
1
2
3
let nickName: String? = nil
let fullName: String = "John Appleseed"
let informalGreeting = "Hi \(nickName ?? fullName)"
Switch 选择语句⽀持任意类型的数据和各种类型的⽐较操作——它不再限制于整型和测试相等
上。
1
2
3
4
5
6
7
8
9
10
11
let vegetable = "red pepper"
switch vegetable {
case "celery":
print("Add some raisins and make ants on a log." )
case "cucumber", "watercress":
print("That would make a good tea sandwich." )
case let x where x.hasSuffix("pepper"):
print("Is it a spicy \(x)?")
default:
print("Everything tastes good in soup.")
}
实验实验
尝试去掉 default选项。会得到什么样的报错?
注意 let 可以⽤在模式⾥来指定匹配的值到⼀个常量当中。
在执⾏完 switch 语句⾥匹配到的 case 之后,程序就会从 switch 语句中退出。执⾏并不会继续跳
到下⼀个 case ⾥,所以完全没有必要显式地在每⼀个 case 后都标记 break 。
你可以使⽤ for-in来遍历字典中的项⽬,这需要提供⼀对变量名来储存键值对。字典使⽤⽆序集
合,所以键值的遍历也是⽆序的。
4/20