简介
这是一个Swift语言教程,基于最新的iOS 9,Xcode 7.3和Swift 2.2,会为你介绍Swift编程非常基础的内容。从电脑如何工作的全程基本原理到语言结构,你会足够了解这门语言,来处理数据和管理代码的行为。
快速链接
- 一个下午让你掌握Swift基础 ( 1/9 ) 编程本质 & Playground基础
- 一个下午让你掌握Swift基础 ( 2/9 ) 变量 & 常量
- 一个下午让你掌握Swift基础 ( 3/9 ) 数字类型 & 操作
- 一个下午让你掌握Swift基础 ( 4/9 ) 字符串
- 一个下午让你掌握Swift基础 ( 5/9 ) 做判断
- 一个下午让你掌握Swift基础 ( 6/9 ) 重复步骤
- 一个下午让你掌握Swift基础 ( 7/9 ) 函数
- 一个下午让你掌握Swift基础 ( 8/9 ) 闭包
- 一个下午让你掌握Swift基础 ( 9/9 ) 可选值
- Swift 初学者 ( 10/12 ) 数组
- Swift 初学者 ( 12/12 ) 集合
字典
字典(dictionary)是没有顺序的一对一对的集合,每一对由一个键(key)和一个值(value)组成。
在上面的示意图可以看到,键是唯一的。相同的键不能在一个字典里出现两次,但不同的键可以指向相同的值。所有的键都要是相同的类型,所有的值也要是相同的类型。
当你想通过一个标识符查找值时,字典很有用。例如,这篇教程内容的表格映射了章节名到他们的链接,让你轻松地就可以快速跳到想阅读的章节。
这和数组有什么不同?用数组,你只能通过它的索引获取一个值,必须要是整数,并且所有索引都要是按顺序的。在一个字典里,键可以是任意类型,也不需要有特定的顺序。
创建字典
当你在创建字典的时候,你可以显示声明键的类型和值的类型。这是字典显示声明的例子:
let pairs: Dictionary
这和数组的显示声明相似,但这里的尖括号里有两个类型,用逗号间隔:键的类型和值的类型。这个例子里,paris 是一个不可以被修改的字典,字符串作为键,整数作为值。
隐式声明
Swift 也能从初始化的类型中推断出字典的类型:
let inferredPairs = Dictionary()
或者用更推荐的简写:
let alsoInferredPairs = [String: Int]()
在方括号里,键的类型后面跟着一个冒号,然后是值的类型。这是声明字典最常用的方式,你会在本教程里全程使用它。
字典字面值
如果你想用初始值声明一个字典,你可以使用字典字面值。这是用逗号间隔的键值对列表,包裹在方括号里。
对于上一篇教程里你的纸牌游戏,不需要使用两个数组来映射选手到他们的分数,用字典字面值就好了:
let namesAndScores = ["Anna": 2, "Brian": 2, "Craig": 8, "Donna": 6]
print(namesAndScores)
// > ["Brian": 2, "Anna": 2, "Craig": 8, "Donna": 6]
这个例子里,字典有一对对 [String: Int]。当你打印字典的时候,可以看到这几对并没有特殊的顺序。
空的字典字面值看起来像这样:[:]。你可以像这样使用它来把一个已经存在的字典清空:
var emptyDictionary: [Int: Int]
emptyDictionary = [:]
访问值
就像数组一样,有几种方式来访问字典的值。
使用下标
字典支持下标来访问值。不像数组,不是用索引来访问值,而是用它的键。例如你希望得到 Anna 的分数,就这样输入:
print(namesAndScores["Anna"])
// > Optional(2)
注意返回值是可选值。字典会检查有没有哪一对的键是“Anna”,如果有,返回它的值。如果字典没有找到键,返回 nil。
print(namesAndScores["Greg"])
// > nil
还记得数组如果下标越界访问就会导致一个运行时错误吗,但字典不同,因为他们的结果被包装为可选值。
你现在可能还没有理解,但可选值的下标访问真的强大。它允许你找一个特定选手是否在游戏里,而不需要遍历所有的键,但使用数组的话就必须要这么做了。
使用 properties 和方法
字典有相同的 isEmpty 和 count properties,和数组一样:
print(namesAndScores.isEmpty)
// > false
print(namesAndScores.count)
// > 4
如果你只想看字典的键或值,你可以从字典的 keys 或 values properties 创建一个数组,各自的:
print(Array(namesAndScores.keys))
// > ["Brian", "Anna", "Craig", "Donna"]
print(Array(namesAndScores.values))
// > [2, 2, 8, 6]
这些就是你在前一篇文章里学的常规数组。
修改字典
添加对
Bob 想加入游戏。
让他加入之前看看他的信息:
var bobData = ["name": "Bob", "profession": "Card Player", "country": "USA"]
这个字典是 [String: String] 类型的,它可以被修改因为被分配到变量了。假设你获得了更多关于 Bob 的信息,想把它加到字典里。这么做:
bobData.updateValue("CA", forKey: "state")
甚至还有一个更短的方式,使用下标:
bobData["city"] = "San Francisco"
Bob 是一个职业纸牌选手。到目前为止,他听起来很适合填入你的名单。
迷你练习
写一个函数,打印给定选手的城市和国家。
更新值
又出现了之前的情况,Bob 曾经在玩牌的时候被逮到作弊。他不只是专业的,还是出老千的!他让你改掉他的名字和职业,这样就没人会认出他了。
看起来 Bob 热切的希望浪子回头,你同意了。首先,你把他的名字从 Bob 改为了 Bobby:
bobData.updateValue("Bobby", forKey: "name")
// > Bob
你读添加对的时候就已经看过这个方法了。为什么它返回字符串“Bob”?updateValue(_:forKey:) 用新的值替换了给定键的值,然后返回老的值。如果键不存在,这个方法会添加新的一对,然后返回 nil。
就像添加一样,你可以用更少的代码来完成,使用下标:
bobData["profession"] = "Mailman"
就像第一个方法,代码更新了这个键的值,或者如果键不存在,创建新的一对。
移除对
Bob-额,抱歉-Bobby,还是觉得不够安全,他希望你移除所有有关他来自哪里的信息:
bobData.removeValueForKey("state")
这个方法会移除“state”键以及它在字典中的关联值。就像你可能预料到的,使用下标是更简短的方式:
bobData["city"] = nil
分配 nil 为一个键的关联值会从字典中移除这一对。
遍历字典
当你想遍历字典的时候,for-in 循环也是有效的。但因为字典里的项目都是成对的,你需要用元组:
for (key, value) in namesAndScores {
print("\(key) - \(value)")
}
// > Brian - 2
// > Anna - 2
// > Craig - 8
// > Donna - 6
只遍历键也是可以的:
for key in namesAndScores.keys {
print("\(key), ", terminator: "") // no newline
}
print("") // print one final newline
// > Brian, Anna, Craig, Donna,
你可以用同样的方式只遍历值,通过字典的 values property。
序列操作
你也可以对字典做序列操作。例如,你可以用 reduce(_:combine:) 来替换前一个代码片段为只一行代码:
let namesString = namesAndScores.reduce("", combine: { $0 + "\($1.0), " })
print(namesString)
在一个 reduce 语句里,$0 是指部分合并的结果,$1 指向当前元素。因为字典的元素是元祖,你需要使用 $1.0 来获得这一对的键。
让我们看看如何用 filter(_:) 来找到所有分数不足 5 的选手:
print(namesAndScores.filter({ $0.1 < 5 }))
// > [("Brian", 2), ("Anna", 2)]
这里用 $0.1 来访问这一对的值。
字典操作的运行时间
为了能够检测字典是如何运作的,需要理解哈希(hashing)是什么,以及它是如何工作的。哈希是转换值 - String, Int, Double, Bool, 等等 - 到数字化的值的过程,叫做哈希值。
Swift 里,所有基本类型都是可以被哈希的,并且有一个 hashValue property。这是例子:
print("some string".hashValue)
// > 4799450059642629719
print(1.hashValue)
// > 1
print(false.hashValue)
// > 0
哈希值必须是确定性的 - 意味着给定一个值必须总是返回同样的哈希值。不论你计算“some string”的哈希值,总是会得到相同的值。
字典只能存储可以被哈希的键。这是一个超出本教程范围的细节实现了,但处理哈希让检查独一性和搜索更轻松了。
这是多种字典操作表现的消耗:
分配元素:获得指定键的值是一个常量时间操作,即O(1)。
加入元素:要插入一个元素,字典需要计算这个键的哈希值,然后基于那个哈希来存储数据。这些都是 O(1) 操作。
删除元素:再一次,字典需要计算哈希值来确切了解在哪里可以找到元素,然后移除它。这也是一个 O(1) 操作。
搜索元素:像上面提到的,访问元素有一个常量运行时间,所以搜索的复杂度也是 O(1)。
关键点
- 字典是没有顺序的键值对集合。
- 字典的键都是相同类型的,值也是相同类型的。
- 使用 下标 来获得值,以及添加、更新或移除对。
- 遍历字典会返回元祖,同时包含键和值。
接下来去哪儿?
字典和数组相当不同:他们没有顺序,有键和值,以及有杰出的搜索表现。
但是,接口在下标和 for-in 循环上很相似。你会在后面学习到,“协议”,这个相似性要感谢跨越集合类型通用的接口。
在下一篇,你会学习集合(sets),结合了你已经从字典和数组里学到的概念。
挑战
挑战 A:你就是编译器
下列哪个是有效语句?
1. let dict1 = Int, Int()
2. let dict2 = []
3. let dict3 = [Int: Int]()
对于接下来四个语句,使用下面的字典:
let dict4 = ["One": 1, "Two": 2, "Three": 3]
4. dict4[1]
5. dict4["One"]
6. dict4["Zero"] = 0
7. dict4[0] = "Zero"
对于接下来的三个语句,使用下面的字典:
var dict5 = ["NY": "New York", "CA": "California"]
8. dict5["NY"]
9. dict5["WA"] = "Washington"
10. dict5["CA"] = nil
挑战 B:替换字典值
写一个函数,交换字典里两个键的值。这是函数结构:
func swapValueForKey(key1: String, withValueForKey key2: String, inDictionary: [String: Int]) -> [String: Int]
挑战 C:搜索字典
给定一个字典,以两个字母的州代号为键,并以完整的州名为值,写一个函数输出所有名字不超过八个字符的州。例如,对于字典 ["NY": "New York", "CA":"California"],输出应该是 “California”。
挑战 D:组合字典
写一个函数,把两个字典组合为一个。如果一个特定的键在两个字典都出现了,忽略第一个字典的对。这是函数结构:
func combine(dict1: [String: String], with dict2: [String: String]) ->[String: String]
挑战源代码
https://yunpan.cn/cMwZ6jA956jsC (提取码:0df7)
介绍
欢迎来到Swift世界!Swift是一门苹果在2014年夏天发布的编程语言。从那之后,Swift发布了一个主要的版本跳跃,成为了开始在苹果平台:iOS,OS X,watchOS和tvOS开发的最简单的方式。
谁适合这篇教程
这篇教程适合懂一点编程、并且希望学习Swift的人。也许你已经为网站写过一些JavaScript代码,或者用Python写过一些简短的程序。这篇教程就是为你准备的!你会学习到编程的基本概念,同时也会成为Swift语言小能手。
如果你是赤裸裸的编程新手,这篇教程也是为你准备的!教程里贯穿有简短的锻炼和挑战来给你一些编程练习,同时测试你的知识。
需要准备什么
要看这篇教程,你需要准备如下的东西:
- 一台运行OS X El Captian(10.11)的Mac,带有最新发布的更新并且安装了安全补丁。这样你才能够安装需要的开发工具:最新版本的Xcode。
- Xcode 7.3 或更新的版本。Xcode是用Swift写代码的主要开发工具。最小也需要Xcode 7.3版本,因为那个版本包含Swift 2.2。你可以免费从Mac App Store下载Xcode的最新版本,这里:http://apple.co/1FLn51R。
如果你还没有安装Xcode最新版本,在继续看下面的教程前要确定安装。
如何使用这篇教程
每篇教程都会介绍触手可及的话题理论,伴随大量Swift代码来示范在学习的实际的应用程序。
教程里的所有代码都是平台中立的;这意味着不是为iOS、OS X或任何其它平台而特定。代码在playgrounds里运行,你在本篇中已经学习了。
在剩下的教程里,你可以把代码在自己的playground里输入进去。这样你就可以和代码“玩耍”(play around),做一些改变立即就能看见代码运行的结果。
剩下的教程里会贯穿实际小练习,都是简短的练习,关于触手可及的主题。每篇的末尾也有挑战,会有编程问题也会有长一点的代码练习来测试你的知识。做完就能掌握大部分的Swift基础知识。