学习 Swift 编程:教程指南
Swift,苹果公司于2014年推出的一种强大且直观的编程语言,迅速成为了构建各种应用的首选工具,尤其是针对苹果生态系统(iOS、macOS、watchOS、tvOS、iPadOS)。但Swift的野心远不止于此,它也是一门开源语言,其应用范围已扩展到服务器端编程和跨平台开发。
对于希望进入苹果开发领域、构建自己的App,或者仅仅对现代编程语言感兴趣的人来说,学习Swift是一个极好的选择。它结合了C和Objective-C的强大功能,同时提供了更现代的语法、更高的安全性和更佳的性能。
本指南将带你踏上Swift编程的学习之旅。我们将从基础概念开始,逐步深入,为你提供一个全面而系统的学习框架。
目录
- Swift 是什么?为何选择 Swift?
- 准备工作:安装 Xcode 与 Swift Playgrounds
- Swift 基础:变量、常量与数据类型
- 运算符:理解如何处理数据
- 控制流:让你的代码根据条件执行
- 条件语句:if、else if、else
- 循环:for-in、while、repeat-while
- switch 语句
- 集合类型:组织你的数据
- 数组 (Arrays)
- 字典 (Dictionaries)
- 集合 (Sets)
- 函数:封装可重用的代码块
- 定义与调用函数
- 参数与返回值
- 外部参数名与内部参数名
- Swift 特性精讲:让 Swift 更安全、更强大
- 可选类型 (Optionals):处理 nil 的安全方式
- 错误处理 (Error Handling):优雅地应对运行时错误
- 闭包 (Closures):强大的匿名函数
- 面向对象与结构化编程:类、结构体、枚举与协议
- 类 (Classes) 与结构体 (Structs):值类型与引用类型的区别
- 枚举 (Enums):定义一组相关的值
- 属性 (Properties) 与方法 (Methods)
- 协议 (Protocols):定义行为规范
- 进阶之路:UI 开发(SwiftUI/UIKit)、并发等
- 学习资源推荐:继续深造的方向
- 总结:开启你的 Swift 编程之旅
1. Swift 是什么?为何选择 Swift?
Swift 是什么?
Swift 是由苹果公司开发的一种多范式、编译型编程语言。它被设计得安全、快速且富有表现力。Swift 取代了 Objective-C 成为苹果平台(iOS, macOS, watchOS, tvOS, iPadOS)应用开发的主要语言。
Swift 的核心特性:
- 安全 (Safe): Swift 强制要求在使用变量之前进行初始化,并使用强大的可选类型(Optionals)来处理值可能缺失的情况,这大大减少了运行时错误和程序崩溃的可能性。它在编译时就能捕获许多传统语言中只能在运行时发现的错误。
- 快速 (Fast): Swift 使用高性能的 LLVM 编译器技术,并采用了现代编程技术的优化手段,其性能在许多任务中可以与 C++ 相媲美。
- 富有表现力 (Expressive): Swift 语法简洁、清晰,易于阅读和编写。它支持多种编程范式,包括面向对象、函数式和协议导向编程。
- 现代 (Modern): Swift 借鉴了许多现代编程语言的最佳实践,包括模式匹配、泛型、类型推断等。
为何选择 Swift?
- 苹果生态系统开发: 如果你想开发 iPhone、iPad、Mac 或 Apple Watch 应用,Swift 是你的首选语言。这是进入一个巨大且盈利潜力巨大的市场的敲门砖。
- 性能优异: 对于需要高性能的应用,Swift 提供了强大的支持。
- 安全性高: Swift 的安全特性可以帮助开发者写出更健壮、更少 bug 的代码。
- 易于学习 (相对而言): 尽管 Swift 功能强大,但其语法设计相对友好,对于有其他编程经验的人来说,上手速度通常较快。对于完全的编程新手,它也是一个不错的起点,特别是通过 Playgrounds 的互动学习方式。
- 活跃的社区: Swift 拥有一个庞大而活跃的开发者社区,这意味着你可以轻松找到学习资源、解决问题和与其他开发者交流。
- 开源且跨平台: Swift 不仅限于苹果平台。由于其开源性质,它已被移植到 Linux、Windows 等其他平台,可以用于服务器端开发(如 Vapor、Kitura 框架)或其他跨平台项目。
总而言之,学习 Swift 意味着掌握一门现代、强大且用途广泛的语言,为你在移动开发、桌面应用开发乃至更广泛的软件工程领域打开大门。
2. 准备工作:安装 Xcode 与 Swift Playgrounds
开始 Swift 编程之旅的第一步是设置你的开发环境。在苹果平台上,主要的开发工具是 Xcode。
安装 Xcode:
- 要求: Xcode 只能在 macOS 系统上运行。你需要一台 Mac 电脑。
- 下载: 打开 Mac 上的 App Store 应用,搜索 “Xcode”。点击“获取”并安装。Xcode 是一个大型应用(通常几个 GB),下载和安装可能需要一些时间,取决于你的网络速度。
- 启动: 安装完成后,在“应用程序”文件夹中找到 Xcode 并打开它。首次启动时,Xcode 可能会要求你同意许可协议或安装一些额外的组件。
使用 Swift Playgrounds:
Xcode 中包含了一个非常重要的工具,叫做 Swift Playgrounds。这是一个互动式的环境,你可以在其中编写 Swift 代码并立即看到结果。对于学习 Swift 基础语法、测试代码片段和实验新概念来说,Playgrounds 是一个极其高效的工具。
创建你的第一个 Playground:
- 打开 Xcode。
- 在欢迎窗口(或通过 File -> New -> Playground)选择 “Create a new Xcode project”,然后选择 “Playground”。
- 选择一个模板。对于初学者,选择 “Blank” 模板即可。
- 给你的 Playground 命名(例如 “MyFirstSwiftPlayground”)并选择保存位置。
- 点击 “Create”。
一个新的 Playground 窗口会打开。你会在左侧看到一个代码编辑区域,右侧有一个结果区域,可以实时显示代码执行的结果。
“`swift
// 在这里输入你的第一行 Swift 代码
import UIKit // 导入 UIKit 框架,通常在 Playgrounds 中默认导入
var greeting = “Hello, Swift Playground!” // 定义一个变量
print(greeting) // 打印变量的值
// 你可以立即在右侧的结果区域看到 “Hello, Swift Playground!”
// 尝试修改 greeting 的值,看看结果区域如何变化
“`
Playgrounds 是学习 Swift 语法概念的理想场所,强烈建议你利用它来实践本指南中介绍的每个代码示例。
3. Swift 基础:变量、常量与数据类型
每个编程语言都有其基本构建块,Swift 也不例外。了解如何存储和操作数据是第一步。
变量与常量:
- 常量 (Constants): 使用
let
关键字声明。常量一旦赋值,就不能更改其值。选择常量可以提高代码的安全性,因为它可以防止意外的值修改。
swift
let maximumNumberOfLoginAttempts = 10 // 声明一个常量
// maximumNumberOfLoginAttempts = 11 // 这会导致编译错误,因为它是常量 - 变量 (Variables): 使用
var
关键字声明。变量可以在声明后多次更改其值。
swift
var currentLoginAttempt = 0 // 声明一个变量
currentLoginAttempt = 1 // 可以修改变量的值
最佳实践: 优先使用let
声明常量。只有当你确定需要修改值时,才使用var
声明变量。
类型安全与类型推断:
Swift 是一门类型安全的语言。这意味着你不能将一个 String
类型的值赋值给一个 Int
类型的变量,这有助于在编译时发现错误。
Swift 具有强大的类型推断能力。当你声明一个变量或常量并赋初值时,Swift 通常可以自动判断其类型,你不需要显式指定。
swift
let age = 30 // Swift 推断 age 的类型为 Int
var name = "Alice" // Swift 推断 name 的类型为 String
let pi = 3.14159 // Swift 推断 pi 的类型为 Double
当然,你也可以选择显式指定类型,这在某些情况下很有用,比如你声明变量时没有赋初值,或者想指定一个更具体的类型。
“`swift
var welcomeMessage: String // 显式声明 welcomeMessage 为 String 类型,但此时它没有值
welcomeMessage = “Hello!” // 赋值
let awesome: Bool = true // 显式声明 awesome 为 Bool 类型
“`
基本数据类型:
Swift 提供了多种内置的基本数据类型:
- 整型 (Integers):
Int
用于表示整数。根据不同的系统(32位或64位),Int
的大小可能不同。还有其他特定大小的整型,如Int8
,Int16
,Int32
,Int64
,以及无符号整型UInt
,UInt8
等。
swift
let count: Int = 100
let smallNumber: Int8 = 50 - 浮点型 (Floating-Point Numbers):
Double
(双精度浮点数,通常用于大范围和高精度的计算) 和Float
(单精度浮点数,精度要求不高时使用)。Double
是首选类型。
swift
let price: Double = 9.99
let temperature: Float = 25.5 - 布尔型 (Booleans):
Bool
用于表示逻辑值true
或false
。
swift
let isComplete: Bool = false -
字符串 (Strings):
String
用于表示文本序列。可以使用双引号""
定义字符串。
swift
let message = "Welcome to Swift!"
字符串支持通过+
进行拼接,以及字符串插值\(variable/constant)
将变量/常量的值嵌入到字符串中。
swift
let userName = "Bob"
let greeting = "Hello, \(userName)!" // greeting 的值为 "Hello, Bob!" -
字符 (Characters):
Character
用于表示单个字符。
swift
let initial: Character = "A"
4. 运算符:理解如何处理数据
运算符是用于检查、改变或组合值的符号或短语。Swift 支持大多数标准的 C 语言运算符,但也提供了一些特殊的运算符。
-
算术运算符:
+
(加),-
(减),*
(乘),/
(除),%
(求余)。
swift
let sum = 10 + 5 // 15
let difference = 20 - 7 // 13
let product = 4 * 6 // 24
let quotient = 10.0 / 3.0 // 3.333...
let remainder = 10 % 3 // 1
注意: 在 Swift 中,不允许不同数值类型之间直接进行算术运算,需要先进行类型转换。例如,let result = 10 + 3.5
会报错,你需要将其转换为let result = Double(10) + 3.5
或let result = 10 + Int(3.5)
(这将丢失精度)。 -
赋值运算符:
=
(等于)。
swift
var x = 10
x = 20 // 将 x 的值更新为 20 - 复合赋值运算符:
+=
,-=
,*=
,/=
,%=
。
swift
var count = 5
count += 3 // 等同于 count = count + 3,count 现在是 8 - 比较运算符:
==
(等于),!=
(不等于),>
(大于),<
(小于),>=
(大于等于),<=
(小于等于)。比较运算符返回布尔值 (true
或false
)。
swift
let a = 10
let b = 20
let isEqual = (a == b) // false
let isGreater = (b > a) // true -
逻辑运算符: 用于组合或修改布尔逻辑值。
&&
(逻辑与): 如果两个操作数都为 true,结果为 true。||
(逻辑或): 如果至少一个操作数为 true,结果为 true。!
(逻辑非): 反转操作数的值 (true 变 false, false 变 true)。
“`swift
let isSunny = true
let isWarm = false
let goodWeather = isSunny && !isWarm // true && true -> true
let goOutside = isSunny || isWarm // true || false -> true
let stayInside = !goOutside // !true -> false
* **范围运算符:**
swift
* 闭合范围运算符 `...`: 定义一个包含上限和下限的范围。
* 半开范围运算符 `<`: 定义一个包含下限但不包含上限的范围。
for index in 1…5 { // index 将依次为 1, 2, 3, 4, 5
print(index)
}for index in 0..<5 { // index 将依次为 0, 1, 2, 3, 4
print(index)
}
“`
范围运算符在循环和条件判断中非常有用。
5. 控制流:让你的代码根据条件执行
控制流语句允许你控制代码的执行顺序,使其能够根据不同的条件采取不同的行动,或者重复执行某些任务。
条件语句:
-
if / else if / else: 根据一个或多个条件执行不同的代码块。
“`swift
let score = 85if score >= 90 {
print(“优秀”)
} else if score >= 80 {
print(“良好”)
} else if score >= 60 {
print(“及格”)
} else {
print(“不及格”)
}
``
()
Swift 的条件语句**不需要**在条件周围加括号,但**必须**使用花括号
{}` 包围代码块。 -
switch: 针对一个值提供多个可能的匹配分支。Swift 的
switch
语句非常强大,支持多种类型的匹配(包括范围、元组和枚举),并且不需要在每个case
的末尾使用break
,因为默认不会“贯穿”(fallthrough)到下一个 case。如果你确实需要贯穿,可以使用fallthrough
关键字。switch
语句必须是完备的,即需要覆盖所有可能的情况,或者提供一个default
分支。“`swift
let grade = “B”switch grade {
case “A”:
print(“成绩优秀”)
case “B”, “C”: // 匹配多个值
print(“成绩良好或及格”)
case “D”:
print(“成绩需努力”)
default: // 必须包含 default 或覆盖所有可能
print(“无效的成绩”)
}let number = 5
switch number {
case 0:
print(“零”)
case 1…5: // 匹配范围
print(“一到五之间”)
case 6..<10:
print(“六到九之间”)
default:
print(“其他数字”)
}
// 输出 “一到五之间”
“`
循环:
-
for-in: 遍历序列(如范围、数组、字典、字符串的字符)。
“`swift
for i in 1…5 { // 遍历范围
print(“(i) 遍”)
}let fruits = [“Apple”, “Banana”, “Cherry”]
for fruit in fruits { // 遍历数组
print(“我喜欢吃 (fruit)”)
}let colors = [“red”: “红色”, “blue”: “蓝色”]
for (english, chinese) in colors { // 遍历字典(元组)
print(“(english) 是 (chinese)”)
}
“` -
while: 当条件为 true 时,重复执行一个代码块。在每次循环迭代开始前检查条件。
swift
var counter = 0
while counter < 5 {
print("计数:\(counter)")
counter += 1
} -
repeat-while: 在执行完代码块后检查条件。这意味着循环体至少会执行一次。
swift
var i = 0
repeat {
print("执行一次,此时 i = \(i)")
i += 1
} while i < 0 // 条件为 false,但循环体已经执行了一次
控制转移语句:
break
: 立即终止整个控制流语句(循环或 switch)。continue
: 停止当前循环迭代的执行,并开始下一次迭代。
6. 集合类型:组织你的数据
Swift 提供了三种主要的集合类型,用于存储和组织多个值:数组 (Arrays)、字典 (Dictionaries) 和集合 (Sets)。它们都是类型安全的,这意味着你存储在集合中的元素类型必须一致(或遵循相同的协议)。
-
数组 (Arrays): 有序的同类型值集合。你可以通过索引(从 0 开始)访问数组中的元素。
“`swift
var shoppingList = [“鸡蛋”, “牛奶”, “面包”] // 类型推断为 [String]// 访问元素
print(shoppingList[0]) // 输出 “鸡蛋”// 修改元素
shoppingList[1] = “酸奶” // shoppingList 现在是 [“鸡蛋”, “酸奶”, “面包”]// 添加元素
shoppingList.append(“香蕉”) // shoppingList 现在是 [“鸡蛋”, “酸奶”, “面包”, “香蕉”]
shoppingList.insert(“黄油”, at: 0) // shoppingList 现在是 [“黄油”, “鸡蛋”, “酸奶”, “面包”, “香蕉”]// 删除元素
let butter = shoppingList.remove(at: 0) // butter 是 “黄油”,shoppingList 少了一个元素
let lastItem = shoppingList.removeLast() // lastItem 是 “香蕉”,shoppingList 少了一个元素// 遍历数组
for item in shoppingList {
print(item)
}// 空数组
var emptyArray: [Int] = [] // 显式声明一个空整型数组
// 或者 var anotherEmptyArray = String
“` -
字典 (Dictionaries): 无序的键值对集合,其中每个键都是唯一的。你可以使用键来查找对应的值。
“`swift
var airports: [String: String] = [“YYZ”: “Toronto Pearson”, “DUB”: “Dublin”] // 类型 [String: String]// 访问值
print(airports[“YYZ”]) // 输出 Optional(“Toronto Pearson”) – 注意返回的是可选类型// 添加或更新值
airports[“LHR”] = “London Heathrow” // 添加新的键值对
airports[“DUB”] = “Dublin Airport” // 更新 DUB 对应的值// 移除值
airports[“YYZ”] = nil // 将值设为 nil 即可移除对应的键值对
// 或者 let removedValue = airports.removeValue(forKey: “DUB”) // 返回被移除的值(可选类型)// 遍历字典
for (airportCode, airportName) in airports {
print(“(airportCode): (airportName)”)
}for airportCode in airports.keys { // 只遍历键
print(airportCode)
}for airportName in airports.values { // 只遍历值
print(airportName)
}// 空字典
var namesOfIntegers: [Int: String] = [:] // 显式声明一个空 Int -> String 字典
// 或者 var anotherEmptyDictionary = String: Int
“`
注意: 字典的键必须是可哈希 (Hashable) 的类型,Swift 的基本类型(String, Int, Double, Bool 等)默认都是可哈希的。 -
集合 (Sets): 无序的同类型值的集合,且集合中的所有元素都必须是唯一的。当你只需要存储一组唯一的项目,而不需要关心它们的顺序时,集合非常有用。
“`swift
var favoriteGenres: Set= [“Rock”, “Classical”, “Hip hop”] // 添加元素
favoriteGenres.insert(“Jazz”) // 如果元素已存在,则不添加// 删除元素
if let removedGenre = favoriteGenres.remove(“Rock”) { // remove(_:) 方法返回被移除的元素(可选类型)
print(“(removedGenre) 被移除了”)
} else {
print(“集合中没有 Rock”)
}// 检查是否包含元素
if favoriteGenres.contains(“Jazz”) {
print(“我喜欢 Jazz”)
}// 遍历集合
for genre in favoriteGenres {
print(genre) // 顺序不确定
}// 集合操作
let oddDigits: Set = [1, 3, 5, 7, 9]
let evenDigits: Set = [0, 2, 4, 6, 8]
let singleDigitPrimeNumbers: Set = [2, 3, 5, 7]oddDigits.union(evenDigits).sorted() // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] – 所有数字
oddDigits.intersection(evenDigits).sorted() // [] – 没有交集
oddDigits.subtracting(singleDigitPrimeNumbers).sorted() // [1, 9] – 奇数中不是质数的
singleDigitPrimeNumbers.symmetricDifference(oddDigits).sorted() // [1, 2, 9] – 在其中一个集合但不在两个集合中的
“`
注意: 集合的元素必须是可哈希 (Hashable) 的类型。
7. 函数:封装可重用的代码块
函数是执行特定任务的独立代码块。你可以定义函数,然后在需要时多次调用它们,这有助于组织代码、提高可读性和重用性。
定义与调用函数:
使用 func
关键字定义函数。函数可以接受参数并返回一个值。
“`swift
// 定义一个没有参数和返回值的函数
func greet(person: String) { // person 是参数,类型为 String
print(“Hello, (person)!”)
}
// 调用函数
greet(person: “Alice”) // 输出 “Hello, Alice!”
greet(person: “Bob”) // 输出 “Hello, Bob!”
// 定义一个带有返回值(String)的函数
func sayHello(personName: String) -> String { // -> String 表示返回 String 类型
let greeting = “Hello, ” + personName + “!”
return greeting // 返回值
}
// 调用函数并接收返回值
let welcome = sayHello(personName: “Charlie”) // welcome 的值是 “Hello, Charlie!”
print(welcome)
“`
参数与返回值:
- 参数 (Parameters): 定义函数时在括号中指定,包括参数名和类型。
- 返回值 (Return Value): 使用
->
符号后跟返回类型指定。如果没有返回值,可以省略-> ReturnType
,或者显式写-> Void
或-> ()
。
外部参数名与内部参数名:
Swift 函数的参数可以同时有外部参数名(调用函数时使用的)和内部参数名(函数内部使用的)。默认情况下,从第二个参数开始,内部参数名也作为外部参数名。你可以使用 _
作为外部参数名,表示省略外部参数名。
“`swift
// 默认行为:第二个参数开始,外部名 == 内部名
func greet(person: String, alreadyGreeted: Bool) {
if alreadyGreeted {
print(“Hello again, (person)!”)
} else {
print(“Hello, (person)!”)
}
}
greet(person: “Tim”, alreadyGreeted: true) // 调用时需要外部参数名
// 指定外部参数名
func say(_ message: String, to person: String) { // _ 表示第一个参数没有外部名,to 是第二个参数的外部名
print(“(message), (person)!”)
}
say(“Good morning”, to: “David”) // 调用时需要指定 to:
// 默认参数值
func buildGreeting(for person: String, withGreeting greeting: String = “Hello”) -> String {
return “(greeting), (person)!”
}
buildGreeting(for: “Eve”) // 使用默认值 “Hello, Eve!”
buildGreeting(for: “Eve”, withGreeting: “Hi”) // 使用指定的值 “Hi, Eve!”
// 可变参数 (Variadic Parameters)
func arithmeticMean(_ numbers: Double…) -> Double { // … 表示 numbers 是一个 Double 数组
var total: Double = 0
for number in numbers {
total += number
}
return total / Double(numbers.count)
}
let mean = arithmeticMean(1.0, 2.0, 3.0, 4.0, 5.0) // mean 是 3.0
“`
8. Swift 特性精讲:让 Swift 更安全、更强大
Swift 引入了一些独特的特性,旨在提高代码的安全性、表达力和性能。
-
可选类型 (Optionals):
可选类型是 Swift 中处理值可能缺失(
nil
)的强大机制。它明确地表示一个变量或常量可能包含一个值,或者可能不包含值 (nil
)。这解决了其他语言中因为意外访问空指针(或nil
)而导致的常见错误。用问号
?
来标记可选类型。例如,String?
表示“一个可选的字符串”,它可能包含一个字符串值,也可能不包含任何值(即nil
)。“`swift
let possibleNumber = “123”
let convertedNumber = Int(possibleNumber) // convertedNumber 的类型是 Int? (可选 Int),它包含值 123let invalidNumber = “hello”
let anotherNumber = Int(invalidNumber) // anotherNumber 的类型是 Int?,它包含 nil
“`访问可选类型的值之前,必须先解包 (unwrap) 它。Swift 提供了几种安全解包可选类型的方法:
-
可选绑定 (Optional Binding): 使用
if let
或guard let
结构来安全地检查可选类型是否包含值,并在有值的情况下将值赋值给一个临时常量或变量。
“`swift
if let actualNumber = Int(possibleNumber) { // 如果 convertedNumber 有值,则将值赋给 actualNumber
print(“字符串 (possibleNumber) 可以转换为整数 (actualNumber)”)
} else {
print(“字符串 (possibleNumber) 无法转换为整数”)
}func processNumber(input: String?) {
guard let number = Int(input) else { // 如果 input 不能转换为 Int,则执行 else 块并退出函数
print(“输入无效”)
return
}
// 如果能转换成功,代码会继续执行到这里
print(“成功转换的数字是 (number)”)
}
processNumber(input: “456”) // 输出 “成功转换的数字是 456”
processNumber(input: “abc”) // 输出 “输入无效”
“` -
强制解包 (Forced Unwrapping): 使用感叹号
!
来访问可选类型的值。只有在你确定可选类型一定包含值时才使用它。如果可选类型是nil
,强制解包会导致运行时错误。
“`swift
let myString: String? = “Hello”
let forceUnwrappedString = myString! // 强制解包,获取 “Hello”let nilString: String? = nil
// let crashString = nilString! // 这会导致运行时错误,因为 nilString 是 nil
“` -
可选链式调用 (Optional Chaining): 使用问号
?.
在可选类型的值上调用方法、访问属性或下标。如果可选类型为nil
,整个链式调用会失败,并返回nil
,而不会引发错误。
“`swift
class Residence {
var numberOfRooms = 1
}
class Person {
var residence: Residence? // Person 可能有 Residence,也可能没有
}let john = Person()
// let roomCount = john.residence.numberOfRooms // 这会报错,因为 residence 可能是 nil
let roomCount = john.residence?.numberOfRooms // 使用可选链式调用
// roomCount 的类型是 Int? (可选 Int),因为如果 residence 是 nil,整个表达式的结果就是 nil
“` -
空合运算符 (Nil-Coalescing Operator): 使用
??
为可选类型提供一个默认值。如果可选类型包含值,则使用该值;否则,使用默认值。
“`swift
let defaultColorName = “red”
var userDefinedColorName: String? // nillet colorNameToUse = userDefinedColorName ?? defaultColorName // colorNameToUse 是 “red”
userDefinedColorName = “blue”
let anotherColorNameToUse = userDefinedColorName ?? defaultColorName // anotherColorNameToUse 是 “blue”
“`
-
-
错误处理 (Error Handling):
Swift 提供了一种结构化的方式来处理程序运行时可能遇到的错误。错误处理不同于可选类型,可选类型用于处理值可能缺失的情况,而错误处理用于处理操作可能失败的情况。
遵循
Error
协议的枚举是定义一组相关错误类型的常用方式。“`swift
enum VendingMachineError: Error {
case invalidSelection
case insufficientFunds(coinsNeeded: Int)
case outOfStock
}// 函数中使用 throws 关键字表示它可能抛出错误
func canThrowAnError() throws {
// 根据条件抛出错误
// throw VendingMachineError.insufficientFunds(coinsNeeded: 5)
}// 使用 do-catch 语句来处理可能抛出错误的函数
do {
try canThrowAnError() // 使用 try 调用可能抛出错误的函数
// 如果没有错误抛出,代码会执行到这里
} catch VendingMachineError.invalidSelection {
print(“无效的选择”)
} catch VendingMachineError.insufficientFunds(let coinsNeeded) { // 捕获关联值
print(“钱不够,还需要 (coinsNeeded) 个硬币”)
} catch { // 捕获其他任何错误
print(“发生了一个通用错误:(error)”)
}
“`还有其他处理错误的方式,如
try?
(尝试执行,如果出错则返回nil
) 和try!
(强制执行,如果出错则崩溃,慎用)。 -
闭包 (Closures):
闭包是自包含的功能代码块,可以在代码中传递和使用。它们类似于 C 和 Objective-C 中的 Blocks 以及其他编程语言中的 lambdas。闭包可以捕获和存储其定义上下文中任何常量和变量的引用。
闭包在 Swift 中非常常用,尤其是在处理异步任务、回调以及作为函数参数传递时。
“`swift
// 排序函数示例,接受一个用于比较的闭包作为参数
let names = [“Chris”, “Alex”, “Ewa”, “Barry”, “Daniella”]// 使用一个闭包作为 sort(by:) 方法的参数
let sortedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in
return s1 < s2
})
// sortedNames 的值为 [“Alex”, “Barry”, “Chris”, “Daniella”, “Ewa”]// 闭包的简化语法:类型推断、隐式返回、单表达式闭包隐式参数 ($0, $1…)
let simplifiedSortedNames = names.sorted { $0 < $1 } // 最简形式// 尾随闭包 (Trailing Closure) 语法
let digitNames = [0: “Zero”, 1: “One”, 2: “Two”, / … / 9: “Nine”]
let numbers = [16, 58, 510]let strings = numbers.map { (number) -> String in // map 方法接受一个闭包
var number = number
var output = “”
repeat {
output = digitNames[number % 10]! + output
number /= 10
} while number > 0
return output
}
// strings 的值为 [“OneSix”, “FiveEight”, “FiveOneZero”]
“`
闭包的语法有很多种简化形式,这让 Swift 代码非常简洁,但也需要一些时间来熟悉。
9. 面向对象与结构化编程:类、结构体、枚举与协议
Swift 并非纯粹的面向对象语言,它支持多种编程范式,包括面向对象、基于协议和函数式编程。类、结构体和枚举是构建数据模型的关键。
-
类 (Classes):
类是引用类型 (Reference Types)。类定义了对象(类的实例)的属性(数据)和方法(行为)。类支持继承,一个类可以继承另一个类的特性。
“`swift
class Dog {
var name: String
var breed: Stringinit(name: String, breed: String) { // 初始化器 (Initializer) self.name = name self.breed = breed } func bark() { // 方法 print("汪汪!我的名字叫 \(name)") }
}
let myDog = Dog(name: “Buddy”, breed: “Golden Retriever”) // 创建类的实例
myDog.bark() // 调用方法let anotherDog = myDog // 将 myDog 赋值给 anotherDog
anotherDog.name = “Lucy” // 修改 anotherDog 的 name
print(myDog.name) // 输出 “Lucy”,因为 myDog 和 anotherDog 引用同一个 Dog 实例
“` -
结构体 (Structs):
结构体是值类型 (Value Types)。当你将一个结构体实例赋值给另一个变量/常量或传递给函数时,会进行拷贝。结构体不支持继承。
“`swift
struct Point {
var x: Double
var y: Double
}var point1 = Point(x: 1.0, y: 2.0) // 创建结构体实例
var point2 = point1 // 将 point1 赋值给 point2,会进行值拷贝point2.x = 3.0 // 修改 point2 的 x
print(point1.x) // 输出 1.0,因为 point1 和 point2 是两个独立的 Point 实例
“`
在 Swift 中,结构体的使用非常广泛,许多内置类型(如 Int, Double, String, Array, Dictionary)都是结构体。苹果推荐在可能的情况下优先使用结构体,因为它们通常更安全(避免了引用类型的意外共享修改)且在某些场景下性能更优。 -
枚举 (Enums):
枚举定义了一组相关的、有限的可能性值。枚举在 Swift 中比在许多其他语言中更强大,可以有关联值 (associated values) 和原始值 (raw values),并且可以定义方法和计算属性。
“`swift
enum CompassPoint { // 定义一个枚举
case north
case south
case east
case west
}var directionToHead = CompassPoint.west
directionToHead = .north // 简化语法switch directionToHead {
case .north:
print(“朝北走”)
case .south:
print(“朝南走”)
case .east:
print(“朝东走”)
case .west:
print(“朝西走”)
}// 带关联值的枚举
enum Barcode {
case upc(Int, Int, Int, Int) // 关联的 Int 元组
case qrCode(String) // 关联的 String
}var productBarcode = Barcode.upc(8, 85909, 51226, 3)
productBarcode = .qrCode(“ABCDEFGHIJKLMNOP”) // 可以更改关联值switch productBarcode {
case .upc(let numberSystem, let manufacturer, let product, let check): // 解包关联值
print(“UPC: (numberSystem), (manufacturer), (product), (check).”)
case .qrCode(let productCode):
print(“QR code: (productCode).”)
}// 带原始值的枚举
enum Planet: Int { // 原始值类型为 Int
case mercury = 1, venus, earth, mars, jupiter, saturn, uranus, neptune
}
let earthOrder = Planet.earth.rawValue // earthOrder 是 3
let possiblePlanet = Planet(rawValue: 7) // possiblePlanet 是 Optional(Planet.uranus)
“` -
协议 (Protocols):
协议定义了类、结构体或枚举必须实现(遵循)的一组方法、属性或其他要求。协议定义的是行为规范,而不是具体实现。协议是 Swift 中实现多态和抽象的重要工具,也是其协议导向编程 (Protocol-Oriented Programming, POP) 范式的核心。
“`swift
protocol FullyNamed { // 定义一个协议
var fullName: String { get } // 要求遵循者提供一个可读的 fullName 属性
}struct Person: FullyNamed { // Struct Person 遵循 FullyNamed 协议
var fullName: String // 实现了协议要求的属性
// … Person 的其他属性和方法
}class Starship: FullyNamed { // Class Starship 遵循 FullyNamed 协议
var name: String
var prefix: String?
var fullName: String { // 实现了协议要求的计算属性
return (prefix ?? “”) + name
}
init(name: String, prefix: String? = nil) {
self.name = name
self.prefix = prefix
}
}let john = Person(fullName: “John Appleseed”)
let enterprise = Starship(name: “Enterprise”, prefix: “USS “)let namedItems: [FullyNamed] = [john, enterprise] // 数组可以包含遵循同一个协议的不同类型的实例
for item in namedItems {
print(item.fullName) // 调用协议要求的属性,表现出多态性
}
“`
协议在构建大型、可维护的代码库中起着至关重要的作用。
10. 进阶之路:UI 开发(SwiftUI/UIKit)、并发等
掌握了 Swift 基础语法后,你就可以开始探索更高级的主题和实际应用开发了。
-
UI 开发: 这是许多人学习 Swift 的主要目的。
- SwiftUI: 苹果于 2019 年推出的声明式 UI 框架。它使用 Swift 的强大功能,通过简洁的语法构建用户界面,支持所有苹果平台,并且可以实时预览。对于新手来说,SwiftUI 通常更容易入门。
- UIKit: 苹果传统的命令式 UI 框架,已经使用了十多年。它功能强大,文档和社区资源非常丰富。许多现有的 App 和库仍然使用 UIKit。了解 UIKit 仍然很有价值。
你通常需要选择其中一个框架作为主要学习方向,或者两者都学习。
-
并发 (Concurrency): 构建响应式应用需要处理耗时任务(如网络请求、数据处理)而不阻塞主线程(UI 线程)。Swift 提供了多种并发模型:
- GCD (Grand Central Dispatch): 基于 C 的底层并发 API,强大但使用起来可能有些复杂。
- Operations: 基于 GCD 的上层抽象,提供更多的控制和状态管理。
- async/await: Swift 5.5 引入的现代、更易读的异步编程模型,基于结构化并发。这是 Swift 推荐的未来并发开发方式。
-
内存管理: Swift 使用 ARC (Automatic Reference Counting) 自动管理内存。理解 ARC 的工作原理以及如何处理循环引用(通过 weak 或 unowned 引用)对于编写无内存泄漏的代码至关重要。
-
泛型 (Generics): 编写灵活、可重用的函数和类型,它们可以用于任何类型,但仍然保持类型安全。
-
高级运算符、下标、继承、初始化流程、类型转换、嵌套类型、扩展 (Extensions) 等。
11. 学习资源推荐:继续深造的方向
学习编程是一个持续的过程。一旦你掌握了 Swift 的基础,以下资源可以帮助你进一步提升:
- 《The Swift Programming Language》官方指南: 由苹果编写,是最权威、最全面的 Swift 语言参考。可以在 Apple Books 中免费获取或在线阅读。
- Apple 官方开发者文档: 学习 SwiftUI、UIKit、Foundation 等框架的必备资源。
- Apple 官方教程: Apple 提供了一些优秀的入门教程,如 SwiftUI 和 UIKit 的官方教程,非常适合实践。
- Stanford CS193p 课程: 斯坦福大学的 iOS 开发公开课,内容深入且高质量,更新到最新技术栈(SwiftUI)。
- Ray Wenderlich (现 Kodeco): 提供了大量的 Swift 和苹果开发教程、视频课程和书籍,是许多开发者学习的首选平台。
- Udemy, Coursera, Hacking with Swift 等在线教育平台: 提供各种Swift和iOS开发的付费课程。
- Stack Overflow: 遇到问题时,搜索和提问的好地方。
- Swift Forums: 官方的 Swift 社区论坛,可以与语言设计者和核心开发者交流。
- GitHub: 查找 Swift 开源项目,学习别人的代码,参与贡献。
- 实践项目: 开始构建自己的小项目。无论是ToDo列表、天气App还是简单的游戏,通过实际动手来巩固知识并学习如何将不同的概念结合起来。
12. 总结:开启你的 Swift 编程之旅
本指南为你提供了一个学习 Swift 编程的全面路线图,从基础语法到核心特性,再到进阶方向。Swift 是一门强大、现代且不断发展的语言,学习它为你打开了通往苹果生态系统乃至更广阔开发领域的道路。
请记住,学习编程最重要的是实践。不要害怕犯错,勇敢地在 Playground 中尝试代码,构建小项目。利用丰富的在线资源和活跃的社区。
现在,是时候启动 Xcode,创建你的第一个 Playground,并开始你的 Swift 编程之旅了!祝你好运,编程愉快!