学习 Swift 编程:教程指南 – wiki基地


学习 Swift 编程:教程指南

Swift,苹果公司于2014年推出的一种强大且直观的编程语言,迅速成为了构建各种应用的首选工具,尤其是针对苹果生态系统(iOS、macOS、watchOS、tvOS、iPadOS)。但Swift的野心远不止于此,它也是一门开源语言,其应用范围已扩展到服务器端编程和跨平台开发。

对于希望进入苹果开发领域、构建自己的App,或者仅仅对现代编程语言感兴趣的人来说,学习Swift是一个极好的选择。它结合了C和Objective-C的强大功能,同时提供了更现代的语法、更高的安全性和更佳的性能。

本指南将带你踏上Swift编程的学习之旅。我们将从基础概念开始,逐步深入,为你提供一个全面而系统的学习框架。

目录

  1. Swift 是什么?为何选择 Swift?
  2. 准备工作:安装 Xcode 与 Swift Playgrounds
  3. Swift 基础:变量、常量与数据类型
  4. 运算符:理解如何处理数据
  5. 控制流:让你的代码根据条件执行
    • 条件语句:if、else if、else
    • 循环:for-in、while、repeat-while
    • switch 语句
  6. 集合类型:组织你的数据
    • 数组 (Arrays)
    • 字典 (Dictionaries)
    • 集合 (Sets)
  7. 函数:封装可重用的代码块
    • 定义与调用函数
    • 参数与返回值
    • 外部参数名与内部参数名
  8. Swift 特性精讲:让 Swift 更安全、更强大
    • 可选类型 (Optionals):处理 nil 的安全方式
    • 错误处理 (Error Handling):优雅地应对运行时错误
    • 闭包 (Closures):强大的匿名函数
  9. 面向对象与结构化编程:类、结构体、枚举与协议
    • 类 (Classes) 与结构体 (Structs):值类型与引用类型的区别
    • 枚举 (Enums):定义一组相关的值
    • 属性 (Properties) 与方法 (Methods)
    • 协议 (Protocols):定义行为规范
  10. 进阶之路:UI 开发(SwiftUI/UIKit)、并发等
  11. 学习资源推荐:继续深造的方向
  12. 总结:开启你的 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:

  1. 要求: Xcode 只能在 macOS 系统上运行。你需要一台 Mac 电脑。
  2. 下载: 打开 Mac 上的 App Store 应用,搜索 “Xcode”。点击“获取”并安装。Xcode 是一个大型应用(通常几个 GB),下载和安装可能需要一些时间,取决于你的网络速度。
  3. 启动: 安装完成后,在“应用程序”文件夹中找到 Xcode 并打开它。首次启动时,Xcode 可能会要求你同意许可协议或安装一些额外的组件。

使用 Swift Playgrounds:

Xcode 中包含了一个非常重要的工具,叫做 Swift Playgrounds。这是一个互动式的环境,你可以在其中编写 Swift 代码并立即看到结果。对于学习 Swift 基础语法、测试代码片段和实验新概念来说,Playgrounds 是一个极其高效的工具。

创建你的第一个 Playground:

  1. 打开 Xcode。
  2. 在欢迎窗口(或通过 File -> New -> Playground)选择 “Create a new Xcode project”,然后选择 “Playground”。
  3. 选择一个模板。对于初学者,选择 “Blank” 模板即可。
  4. 给你的 Playground 命名(例如 “MyFirstSwiftPlayground”)并选择保存位置。
  5. 点击 “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 用于表示逻辑值 truefalse
    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.5let result = 10 + Int(3.5) (这将丢失精度)。

  • 赋值运算符: = (等于)。
    swift
    var x = 10
    x = 20 // 将 x 的值更新为 20

  • 复合赋值运算符: +=, -=, *=, /=, %=
    swift
    var count = 5
    count += 3 // 等同于 count = count + 3,count 现在是 8
  • 比较运算符: == (等于), != (不等于), > (大于), < (小于), >= (大于等于), <= (小于等于)。比较运算符返回布尔值 (truefalse)。
    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 = 85

    if 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),它包含值 123

    let invalidNumber = “hello”
    let anotherNumber = Int(invalidNumber) // anotherNumber 的类型是 Int?,它包含 nil
    “`

    访问可选类型的值之前,必须先解包 (unwrap) 它。Swift 提供了几种安全解包可选类型的方法:

    • 可选绑定 (Optional Binding): 使用 if letguard 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? // nil

      let 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: String

    init(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 编程之旅了!祝你好运,编程愉快!


发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注

滚动至顶部