1、最新版本2015最新版本20151 欢 迎 使 用 Swift在 本 章 中 您 将 了 解 Swift 的 特 性 和 开 发 历 史 , 并 对 Swift 有 一 个 初 步 的 了 解1.1 关 于 SwiftSwift 是 一 种 新 的 编 程 语 言 , 用 于 编 写 iOS 和 OS X 应 用 。 Swift 结 合 了 C 和 Objective-C 的 优 点 并 且 不 受 C 的 兼 容 性 的 限 制 。 Swift 使 用 安 全 的 编 程 模 式 并 添 加 了 很多 新 特 性 , 这 将 使 编 程 更 简 单 , 扩 展 性 更 强 , 也 更 有 趣
2、 。 除 此 之 外 , Swift 还 支 持 人 见 人爱 的 Cocoa 和 Cocoa Touch 框 架 。 拥 有 了 这 些 特 性 , Swift 将 重 新 定 义 软 件 开 发 。Swift 的 开 发 从 很 久 之 前 就 开 始 了 。 为 了 给 Swift 打 好 基 础 , 苹 果 公 司 改 进 了 编 译 器 ,调 试 器 和 框 架 结 构 。 我 们 使 用 自 动 引 用 计 数 ( Automatic Reference Counting, ARC) 来简 化 内 存 管 理 。 我 们 在 Foundation 和 Cocoa 的 基 础 上 构
3、 建 框 架 栈 并 将 其 标 准 化 。Objective-C 本 身 支 持 块 、 集 合 语 法 和 模 块 , 所 以 框 架 可 以 轻 松 支 持 现 代 编 程 语 言 技 术 。得 益 于 这 些 基 础 工 作 , 我 们 现 在 可 以 发 布 一 个 新 语 言 , 用 于 未 来 的 苹 果 软 件 的 开 发 。Objective-C 开 发 者 对 于 Swift 并 不 会 感 到 陌 生 。 它 采 用 了 Objective-C 的 命 名 参 数 以及 动 态 对 象 模 型 , 可 以 无 缝 对 接 到 现 有 的 Cocoa 框 架 , 并 且 可
4、 以 兼 容 Objective-C 代码 。 在 此 基 础 之 上 , Swift 还 有 许 多 新 特 性 并 且 支 持 过 程 式 编 程 和 面 向 对 象 编 程 。Swift 对 于 初 学 者 来 说 也 很 友 好 。 它 是 第 一 个 既 满 足 工 业 标 准 又 像 脚 本 语 言 一 样 充 满 表 现力 和 趣 味 的 编 程 语 言 。 它 支 持 代 码 预 览 , 这 个 革 命 性 的 特 性 可 以 允 许 程 序 员 在 不 编 译 和 运行 应 用 程 序 的 前 提 下 运 行 Swift 代 码 并 实 时 查 看 结 果 。Swift 将
5、现 代 编 程 语 言 的 精 华 和 苹 果 工 程 师 文 化 的 智 慧 结 合 了 起 来 。 编 译 器 对 性 能 进 行 了优 化 , 编 程 语 言 对 开 发 进 行 了 优 化 , 两 者 互 不 干 扰 , 鱼 与 熊 掌 兼 得 。 Swift 即 可 以 用 于 开发 “hello, world”这 样 的 小 程 序 , 也 可 以 用 于 开 发 一 个 完 整 的 操 作 系 统 。 所 有 的 这 些 特 性 让 Swift 对 于 开 发 者 和 苹 果 来 说 都 是 一 项 值 得 的 投 资 。用 Swift 编 写 iOS 和 OS X 应 用 将
6、是 一 场 美 妙 的 体 验 , Swift 之 后 也 会 不 断 开 发 新 特性 和 兼 容 性 。 我 们 对 Swift 充 满 信 心 , 你 还 在 等 什 么 !1.2 Swift 初 见本 页 内 容 包 括 : 简 单 值 控 制 流 函 数 和 闭 包 对 象 和 类最新版本2015最新版本2015 枚 举 和 结 构 体 接 口 和 扩 展 泛 型通 常 来 说 , 编 程 语 言 教 程 中 的 第 一 个 程 序 应 该 在 屏 幕 上 打 印 “Hello, world”。 在 Swift 中 ,可 以 用 一 行 代 码 实 现 :println(“Hello
7、, world“)如 果 你 写 过 C 或 者 Objective-C 代 码 , 那 你 应 该 很 熟 悉 这 种 形 式 在 Swift 中 , 这行 代 码 就 是 一 个 完 整 的 程 序 。 你 不 需 要 为 了 输 入 输 出 或 者 字 符 串 处 理 导 入 一 个 单 独 的 库 。全 局 作 用 域 中 的 代 码 会 被 自 动 当 做 程 序 的 入 口 点 , 所 以 你 也 不 需 要 main 函 数 。 你 同 样 不需 要 在 每 个 语 句 结 尾 写 上 分 号 。这 个 教 程 会 通 过 一 系 列 编 程 例 子 来 让 你 对 Swift
8、有 初 步 了 解 , 如 果 你 有 什 么 不 理 解 的 地方 也 不 用 担 心 任 何 本 章 介 绍 的 内 容 都 会 在 后 面 的 章 节 中 详 细 讲 解 。注 意 : 为 了 获 得 最 好 的 体 验 , 在 Xcode 当 中 使 用 代 码 预 览 功 能 。 代 码 预 览 功 能 可 以 让 你编 辑 代 码 并 实 时 看 到 运 行 结 果 。简 单 值使 用 let 来 声 明 常 量 , 使 用 var 来 声 明 变 量 。 一 个 常 量 的 值 在 编 译 时 并 不 需 要 获 取 , 但是 你 只 能 为 它 赋 值 一 次 。 也 就 是
9、说 你 可 以 用 常 量 来 表 示 这 样 一 个 值 : 你 只 需 要 决 定 一 次 ,但 是 需 要 使 用 很 多 次 。var myVariable = 42myVariable = 50let myConstant = 42常 量 或 者 变 量 的 类 型 必 须 和 你 赋 给 它 们 的 值 一 样 。 然 而 , 声 明 时 类 型 是 可 选 的 , 声 明 的 同时 赋 值 的 话 , 编 译 器 会 自 动 推 断 类 型 。 在 上 面 的 例 子 中 , 编 译 器 推 断 出 myVariable 是一 个 整 数 ( integer) 因 为 它 的 初
10、 始 值 是 整 数 。如 果 初 始 值 没 有 提 供 足 够 的 信 息 ( 或 者 没 有 初 始 值 ) , 那 你 需 要 在 变 量 后 面 声 明 类 型 , 用冒 号 分 割 。let implicitInteger = 70let implicitDouble = 70.0let explicitDouble: Double = 70练 习 : 创 建 一 个 常 量 , 显 式 指 定 类 型 为 Float 并 指 定 初 始 值 为 4。最新版本2015最新版本2015值 永 远 不 会 被 隐 式 转 换 为 其 他 类 型 。 如 果 你 需 要 把 一 个 值
11、转 换 成 其 他 类 型 , 请 显 式 转 换 。let label = “The width is“let width = 94let widthLabel = label + String(width)练 习 : 删 除 最 后 一 行 中 的 String, 错 误 提 示 是 什 么 ?有 一 种 更 简 单 的 把 值 转 换 成 字 符 串 的 方 法 : 把 值 写 到 括 号 中 , 并 且 在 括 号 之 前 写 一 个 反 斜杠 。 例 如 :let apples = 3let oranges = 5let appleSummary = “I have (apples)
12、 apples.“let fruitSummary = “I have (apples + oranges) pieces of fruit.“练 习 : 使 用 ()来 把 一 个 浮 点 计 算 转 换 成 字 符 串 , 并 加 上 某 人 的 名 字 , 和 他 打 个 招 呼 。使 用 方 括 号 来 创 建 数 组 和 字 典 , 并 使 用 下 标 或 者 键 ( key) 来 访 问 元 素 。var shoppingList = “catfish“, “water“, “tulips“, “blue paint“shoppingList1 = “bottle of water
13、“var occupations = “Malcolm“: “Captain“,“Kaylee“: “Mechanic“,occupations“Jayne“ = “Public Relations“要 创 建 一 个 空 数 组 或 者 字 典 , 使 用 初 始 化 语 法 。let emptyArray = String()let emptyDictionary = Dictionary()如 果 类 型 信 息 可 以 被 推 断 出 来 , 你 可 以 用 和 :来 创 建 空 数 组 和 空 字 典 就 像 你 声 明变 量 或 者 给 函 数 传 参 数 的 时 候 一 样 。s
14、hoppingList = / 去 逛 街 并 买 点 东 西最新版本2015最新版本2015控 制 流使 用 if 和 switch 来 进 行 条 件 操 作 , 使 用 for-in、 for、 while 和 do-while 来 进 行 循环 。 包 裹 条 件 和 循 环 变 量 括 号 可 以 省 略 , 但 是 语 句 体 的 大 括 号 是 必 须 的 。let individualScores = 75, 43, 103, 87, 12var teamScore = 0for score in individualScores if score 50 teamScore +
15、= 3 else teamScore += 1teamScore在 if 语 句 中 , 条 件 必 须 是 一 个 布 尔 表 达 式 这 意 味 着 像 if score . 这 样 的 代码 将 报 错 , 而 不 会 隐 形 地 与 0 做 对 比 。你 可 以 一 起 使 用 if 和 let 来 处 理 值 缺 失 的 情 况 。 有 些 变 量 的 值 是 可 选 的 。 一 个 可 选 的 值可 能 是 一 个 具 体 的 值 或 者 是 nil, 表 示 值 缺 失 。 在 类 型 后 面 加 一 个 问 号 来 标 记 这 个 变 量 的值 是 可 选 的 。var opt
16、ionalString: String? = “Hello“optionalString = nilvar optionalName: String? = “John Appleseed“var greeting = “Hello!“if let name = optionalName greeting = “Hello, (name)“练 习 : 把 optionalName 改 成 nil, greeting 会 是 什 么 ? 添 加 一 个 else 语 句 , 当optionalName 是 nil 时 给 greeting 赋 一 个 不 同 的 值 。如 果 变 量 的 可 选
17、值 是 nil, 条 件 会 判 断 为 false, 大 括 号 中 的 代 码 会 被 跳 过 。 如 果 不 是nil, 会 将 值 赋 给 let 后 面 的 常 量 , 这 样 代 码 块 中 就 可 以 使 用 这 个 值 了 。switch 支 持 任 意 类 型 的 数 据 以 及 各 种 比 较 操 作 不 仅 仅 是 整 数 以 及 测 试 相 等 。let vegetable = “red pepper“switch vegetable case “celery“:let vegetableComment = “Add some raisins and make ants
18、 on a log.“最新版本2015最新版本2015case “cucumber“, “watercress“:let vegetableComment = “That would make a good tea sandwich.“case let x where x.hasSuffix(“pepper“):let vegetableComment = “Is it a spicy (x)?“default:let vegetableComment = “Everything tastes good in soup.“练 习 : 删 除 default 语 句 , 看 看 会 有 什 么
19、错 误 ?运 行 switch 中 匹 配 到 的 子 句 之 后 , 程 序 会 退 出 switch 语 句 , 并 不 会 继 续 向 下 运 行 , 所以 不 需 要 在 每 个 子 句 结 尾 写 break。你 可 以 使 用 for-in 来 遍 历 字 典 , 需 要 两 个 变 量 来 表 示 每 个 键 值 对 。let interestingNumbers = “Prime“: 2, 3, 5, 7, 11, 13,“Fibonacci“: 1, 1, 2, 3, 5, 8,“Square“: 1, 4, 9, 16, 25,var largest = 0for (kin
20、d, numbers) in interestingNumbers for number in numbers if number largest largest = numberlargest练 习 : 添 加 另 一 个 变 量 来 记 录 哪 种 类 型 的 数 字 是 最 大 的 。使 用 while 来 重 复 运 行 一 段 代 码 直 到 不 满 足 条 件 。 循 环 条 件 可 以 在 开 头 也 可 以 在 结 尾 。var n = 2while n 来 指 定 函 数 返 回 值 。func greet(name: String, day: String) - Strin
21、g return “Hello (name), today is (day).“greet(“Bob“, “Tuesday“)练 习 : 删 除 day 参 数 , 添 加 一 个 参 数 来 表 示 今 天 吃 了 什 么 午 饭 。使 用 一 个 元 组 来 返 回 多 个 值 。func getGasPrices() - (Double, Double, Double) return (3.59, 3.69, 3.79)getGasPrices()函 数 的 参 数 数 量 是 可 变 的 , 用 一 个 数 组 来 获 取 它 们 :func sumOf(numbers: Int.)
22、- Int var sum = 0最新版本2015最新版本2015for number in numbers sum += numberreturn sumsumOf()sumOf(42, 597, 12)练 习 : 写 一 个 计 算 参 数 平 均 值 的 函 数 。函 数 可 以 嵌 套 。 被 嵌 套 的 函 数 可 以 访 问 外 侧 函 数 的 变 量 , 你 可 以 使 用 嵌 套 函 数 来 重 构 一 个太 长 或 者 太 复 杂 的 函 数 。func returnFifteen() - Int var y = 10func add() y += 5add()return
23、yreturnFifteen()函 数 是 一 等 公 民 , 这 意 味 着 函 数 可 以 作 为 另 一 个 函 数 的 返 回 值 。func makeIncrementer() - (Int - Int) func addOne(number: Int) - Int return 1 + numberreturn addOnevar increment = makeIncrementer()increment(7)函 数 也 可 以 当 做 参 数 传 入 另 一 个 函 数 。func hasAnyMatches(list: Int, condition: Int - Bool)
24、- Bool for item in list 最新版本2015最新版本2015if condition(item) return truereturn falsefunc lessThanTen(number: Int) - Bool return number Int inlet result = 3 * numberreturn result)练 习 : 重 写 闭 包 , 对 所 有 奇 数 返 回 0.有 很 多 种 创 建 闭 包 的 方 法 。 如 果 一 个 闭 包 的 类 型 已 知 , 比 如 作 为 一 个 回 调 函 数 , 你 可 以 忽略 参 数 的 类 型 和 返
25、 回 值 。 单 个 语 句 闭 包 会 把 它 语 句 的 值 当 做 结 果 返 回 。你 可 以 通 过 参 数 位 置 而 不 是 参 数 名 字 来 引 用 参 数 这 个 方 法 在 非 常 短 的 闭 包 中 非 常 有 用 。当 一 个 闭 包 作 为 最 后 一 个 参 数 传 给 一 个 函 数 的 时 候 , 它 可 以 直 接 跟 在 括 号 后 面 。sort(1, 5, 3, 12, 2) $0 $1 对 象 和 类使 用 class 和 类 名 来 创 建 一 个 类 。 类 中 属 性 的 声 明 和 常 量 、 变 量 声 明 一 样 , 唯 一 的 区 别就
26、 是 它 们 的 上 下 文 是 类 。 同 样 , 方 法 和 函 数 声 明 也 一 样 。class Shape var numberOfSides = 0func simpleDescription() - String return “A shape with (numberOfSides) sides.“最新版本2015最新版本2015练 习 : 使 用 let 添 加 一 个 常 量 属 性 , 再 添 加 一 个 接 收 一 个 参 数 的 方 法 。要 创 建 一 个 类 的 实 例 , 在 类 名 后 面 加 上 括 号 。 使 用 点 语 法 来 访 问 实 例 的 属
27、性 和 方 法 。var shape = Shape()shape.numberOfSides = 7var shapeDescription = shape.simpleDescription()这 个 版 本 的 Shape 类 缺 少 了 一 些 重 要 的 东 西 : 一 个 构 造 函 数 来 初 始 化 类 实 例 。 使 用 init来 创 建 一 个 构 造 器 。class NamedShape var numberOfSides: Int = 0var name: Stringinit(name: String) self.name = namefunc simpleDes
28、cription() - String return “A shape with (numberOfSides) sides.“注 意 self 被 用 来 区 别 实 例 变 量 。 当 你 创 建 实 例 的 时 候 , 像 传 入 函 数 参 数 一 样 给 类 传 入 构造 器 的 参 数 。 每 个 属 性 都 需 要 赋 值 无 论 是 通 过 声 明 ( 就 像 numberOfSides) 还 是 通过 构 造 器 ( 就 像 name) 。如 果 你 需 要 在 删 除 对 象 之 前 进 行 一 些 清 理 工 作 , 使 用 deinit 创 建 一 个 析 构 函 数
29、。子 类 的 定 义 方 法 是 在 它 们 的 类 名 后 面 加 上 父 类 的 名 字 , 用 冒 号 分 割 。 创 建 类 的 时 候 并 不 需要 一 个 标 准 的 根 类 , 所 以 你 可 以 忽 略 父 类 。子 类 如 果 要 重 写 父 类 的 方 法 的 话 , 需 要 用 override 标 记 如 果 没 有 添 加 override 就重 写 父 类 方 法 的 话 编 译 器 会 报 错 。 编 译 器 同 样 会 检 测 override 标 记 的 方 法 是 否 确 实 在 父类 中 。class Square: NamedShape var side
30、Length: Double最新版本2015最新版本2015init(sideLength: Double, name: String) self.sideLength = sideLengthsuper.init(name: name)numberOfSides = 4func area() - Double return sideLength * sideLengthoverride func simpleDescription() - String return “A square with sides of length (sideLength).“let test = Square(
31、sideLength: 5.2, name: “my test square“)test.area()test.simpleDescription()练 习 : 创 建 NamedShape 的 另 一 个 子 类 Circle, 构 造 器 接 收 两 个 参 数 , 一 个 是 半 径 一 个是 名 称 , 实 现 area 和 describe 方 法 。属 性 可 以 有 getter 和 setter 。class EquilateralTriangle: NamedShape var sideLength: Double = 0.0init(sideLength: Double, name: String) self.sideLength = sideLengthsuper.init(name: name)numberOfSides = 3var perimeter: Double get return 3.0 * sideLengthset sideLength = newValue / 3.0