Swift 初探:从变量到并发,一文带你零基础读懂官方 Tour

简单值(Simple Values)

  1. 常量与变量
swift 复制代码
// 常量:一次性赋值
let maximumNumberOfLoginAttempts = 10
// 变量:可反复修改
var currentLoginAttempt = 0

编译器自动推断类型,也可以显式标注:

swift 复制代码
let π: Double = 3.14159
  1. 类型转换必须显式
swift 复制代码
let width = 94
let message = "The width is " + String(width)   // ✅ 必须包一层
// Swift 不支持隐式转换:String + Int → 编译错误
  1. 字符串插值(推荐写法)
swift 复制代码
let apples = 3
let oranges = 5
let fruitSummary = "I have \(apples + oranges) pieces of fruit."
  1. 多行字符串
swift 复制代码
let quotation = """
Even though there's whitespace to the left,
the actual lines aren't indented.
    But this line is indented!
"""
// 缩进以结尾 """ 的位置为准,自动裁剪左侧空格。
  1. 数组 & 字典
swift 复制代码
var shoppingList = ["eggs", "milk"]          // 数组自动 [String]
shoppingList.append("flour")                 // 可追加

var occupations = ["Malcolm": "Captain",
                   "Kaylee": "Mechanic"]
occupations["Jayne"] = "Public Relations"    // 新增键值

空数组、空字典写法:

swift 复制代码
let emptyArray: [String] = []
let emptyDict: [String: Float] = [:]
// 如果左侧无类型信息,必须显式声明类型

控制流(Control Flow)

  1. if / switch / for / while 概览
swift 复制代码
let score = 99
if score > 90 {
    print("Great")
} else {
    print("OK")
}

条件必须是 Bool,不能写 if score { ... }(C 语言坏习惯在这里直接报错)。

  1. 可选型(Optional)
swift 复制代码
var optionalString: String? = "Hello"
optionalString = nil        // 现在里面没东西

// 经典拆包
if let name = optionalString {
    print("The name is \(name)")
} else {
    print("No name")
}

// 提供默认值
let nickName = optionalString ?? "anonymous"
  1. switch 可以匹配任意类型,不用 break
swift 复制代码
let vegetable = "red pepper"
switch vegetable {
case "celery":
    print("Add raisins")
case let x where x.hasSuffix("pepper"):
    print("Is it a spicy \(x)?")
default:
    print("Everything else")
}
// 匹配成功后自动跳出,不会 fallthrough
  1. 区间运算符
swift 复制代码
// 半开区间:0..<4  → 0,1,2,3
// 闭合区间:0...4  → 0,1,2,3,4
for n in 0..<4 {
    print(n)
}

函数与闭包(Functions & Closures)

  1. 函数定义 & 调用
swift 复制代码
@discardableResult
func greet(person: String, day: String) -> String {
    return "Hello \(person), today is \(day)."
}
greet(person: "Tom", day: "Wednesday")

默认参数名就是标签,可自定义:

swift 复制代码
func greet(_ person: String, on day: String) -> String {
    return "Hello \(person), today is \(day)."
}
greet("Tom", on: "Wednesday")
  1. 返回多值:Tuple
swift 复制代码
func calculate(scores: [Int]) -> (min: Int, max: Int, sum: Int) {
    var min = scores[0], max = scores[0], sum = 0
    for s in scores {
        if s < min { min = s }
        if s > max { max = s }
        sum += s
    }
    return (min, max, sum)
}
let statistics = calculate(scores: [5, 3, 100, 9])
print(statistics.sum)   // 117
print(statistics.2)     // 下标也行
  1. 嵌套函数 = 闭包的一种
swift 复制代码
func returnFifteen() -> Int {
    var y = 10
    func add() { y += 5 }   // 嵌套函数可以捕获外部变量
    add()
    return y
}
  1. 一等公民:函数作参数 / 返回值
swift 复制代码
func makeIncrementer() -> ((Int) -> Int) {
    func addOne(number: Int) -> Int {
        return 1 + number
    }
    return addOne
}
var increment = makeIncrementer()
increment(7)   // 8
  1. 闭包简写(实际开发最常用)
swift 复制代码
let numbers = [2, 19, 7, 42]
var result = numbers.map({ number in 3 * number })
// 更简:numbers.map { 3 * $0 }
print(result)   // [6, 57, 21, 126]

如果闭包是最后一个实参,可写在括号外;唯一实参可省略括号:

swift 复制代码
let sorted = numbers.sorted { $0 > $1 }

对象与类(Objects & Classes)

  1. 最简单的类
swift 复制代码
class Shape {
    var numberOfSides = 0
    func simpleDescription() -> String {
        return "A shape with \(numberOfSides) sides."
    }
}

var shape = Shape()
shape.numberOfSides = 7
print(shape.simpleDescription())
  1. 指定构造器(init)与析构器(deinit)
swift 复制代码
class NamedShape {
    var numberOfSides: Int
    let name: String

    init(name: String, sides: Int) {
        self.name = name
        self.numberOfSides = sides
    }

    deinit {
        // 对象释放前清理,比如关闭文件
        print("\(name) is being deinitialized")
    }

    func description() -> String {
        return "\(name) with \(numberOfSides) sides"
    }
}
  1. 继承 & 重写(override)
swift 复制代码
class Square: NamedShape {
    var sideLength: Double

    init(sideLength: Double, name: String) {
        self.sideLength = sideLength
        super.init(name: name, sides: 4)
    }

    func area() -> Double {
        return sideLength * sideLength
    }

    override func description() -> String {
        return "Square: \(super.description()), area=\(area())"
    }
}
  1. 存储属性 vs 计算属性
swift 复制代码
class EquilateralTriangle: NamedShape {
    var sideLength: Double = 0.0

    init(sideLength: Double, name: String) {
        self.sideLength = sideLength
        super.init(name: name, sides: 3)
    }

    // 计算属性
    var perimeter: Double {
        get { return 3 * sideLength }
        set {
            // newValue 是隐式参数
            sideLength = newValue / 3
        }
    }
}
  1. 属性观察器(willSet / didSet)
swift 复制代码
class TriangleAndSquare {
    var triangle: EquilateralTriangle {
        willSet {
            print("Triangle will change, new side=\(newValue.sideLength)")
        }
        didSet {
            // 保证 square 与 triangle 边长同步
            square.sideLength = triangle.sideLength
        }
    }
    var square: Square {
        didSet {
            triangle.sideLength = square.sideLength
        }
    }

    init(size: Double, name: String) {
        square = Square(sideLength: size, name: "sq")
        triangle = EquilateralTriangle(sideLength: size, name: "tri")
    }
}
  1. 可选链(?)
swift 复制代码
let optionalSquare: Square? = Square(sideLength: 2.5, name: "opt sq")
let side = optionalSquare?.sideLength   // 如果为 nil 则返回 nil

枚举与结构体(Enum & Struct)

  1. 枚举可以带方法
swift 复制代码
enum Rank: Int {
    case ace = 1
    case two, three, four, five, six, seven, eight, nine, ten
    case jack, queen, king

    func simpleDescription() -> String {
        switch self {
        case .ace: return "ace"
        case .jack: return "jack"
        case .queen: return "queen"
        case .king: return "king"
        default: return String(self.rawValue)
        }
    }
}
let ace = Rank.ace
print(ace.simpleDescription())   // ace
  1. 从原始值构造(可失败)
swift 复制代码
if let converted = Rank(rawValue: 11) {
    print(converted.simpleDescription())   // jack
}
  1. 关联值(真正强大的地方)
swift 复制代码
enum ServerResponse {
    case result(String, String)   // 日出、日落
    case failure(String)          // 错误描述
}

let response = ServerResponse.result("06:00", "20:30")
switch response {
case let .result(sunrise, sunset):
    print("Sunrise at \(sunrise), sunset at \(sunset)")
case let .failure(msg):
    print("Server error: \(msg)")
}
  1. 结构体(值类型)
swift 复制代码
struct Card {
    var rank: Rank
    var suit: Suit   // 假设已有枚举 Suit

    func description() -> String {
        return "The \(rank.simpleDescription()) of \(suit.simpleDescription())"
    }
}

结构体复制传值,类引用传值;这是 Swift 与 Java 最大的不同之一。

并发(Concurrency)

需要 Swift ≥5.5,编译目标 macOS 12 / iOS 15 以上

  1. async / await 基础
swift 复制代码
func fetchUserID(from server: String) async -> Int {
    // 模拟网络等待
    try? await Task.sleep(nanoseconds: 1_000_000_000)
    return Int.random(in: 1...999)
}

func userName(id: Int) async -> String {
    try? await Task.sleep(nanoseconds: 500_000_000)
    return "user\(id)"
}
  1. 顺序调用
swift 复制代码
let id = await fetchUserID(from: "primary")
let name = await userName(id: id)
print(name)
  1. 并行调用(async let)
swift 复制代码
async let id = fetchUserID(from: "primary")
async let name = userName(id: 234) 
let ret = await name + "====id:\(id)"
print(ret))
  1. 从同步上下文调用(Task)
swift 复制代码
Task {
    let id = await fetchUserID(from: "backup")
    print("Got id \(id)")
}
  1. Actor:线程安全的"类"
swift 复制代码
actor TemperatureLogger {
    private var records: [Double] = []
    let label: String

    init(label: String) {
        self.label = label
    }

    func update(with reading: Double) {
        records.append(reading)
    }

    func average() -> Double {
        return records.reduce(0, +) / Double(records.count)
    }
}

let logger = TemperatureLogger(label: "Living room")
await logger.update(with: 22.5)
print(await logger.average())

访问 actor 内部状态必须 await,编译器自动保证互斥。

协议与扩展(Protocols & Extensions)

  1. 协议定义
swift 复制代码
protocol ExampleProtocol {
    var simpleDescription: String { get }
    mutating func adjust()   // 结构体实现时需加 mutating
}
  1. 类 / 结构体 / 枚举都能遵守
swift 复制代码
class SimpleClass: ExampleProtocol {
    var simpleDescription: String = "A very simple class"
    var anotherProperty: Int = 69105

    func adjust() {
        simpleDescription += " (adjusted)"
    }
}

struct SimpleStructure: ExampleProtocol {
    var simpleDescription: String = "A simple structure"

    // 结构体是值类型,修改自身方法需 mutating
    mutating func adjust() {
        simpleDescription += " (adjusted)"
    }
}
  1. 扩展为已有类型加功能
swift 复制代码
extension Int: ExampleProtocol {
    var simpleDescription: String {
        return "The number \(self)"
    }

    mutating func adjust() {
        self += 42
    }
}
  1. 把协议当类型用
swift 复制代码
let protocolValue: ExampleProtocol = SimpleClass()
print(protocolValue.simpleDescription)
// 编译器只能看到协议里定义的成员,anotherProperty 不可见

异常处理(Error Handling)

  1. 定义错误
swift 复制代码
enum PrinterError: Error {
    case outOfPaper
    case noToner
    case onFire
}
  1. 抛错 & 标记
swift 复制代码
func send(job: Int, toPrinter printerName: String) throws -> String {
    if printerName == "Never Has Toner" {
        throw PrinterError.noToner
    }
    return "Job sent"
}
  1. do-catch 处理
swift 复制代码
do {
    let result = try send(job: 1040, toPrinter: "Never Has Toner")
    print(result)
} catch PrinterError.noToner {
    print("请更换墨粉")
} catch {   // 兜底
    print("其他打印错误:\(error)")
}
  1. try? 转可选
swift 复制代码
let result = try? send(job: 1440, toPrinter: "Gutenberg")
// 成功则包 .some,失败为 nil,适合不关心具体错误场景
  1. defer:扫尾工作
swift 复制代码
func processFile(filename: String) throws {
    let file = open(filename, 2)
    defer {
        close(file)   // 函数退出前**一定**执行
    }
    try operate(on: file)
}

泛型(Generics)

  1. 泛型函数
swift 复制代码
func makeArray<Item>(repeating item: Item, numberOfTimes: Int) -> [Item] {
    var result: [Item] = []
    for _ in 0..<numberOfTimes {
        result.append(item)
    }
    return result
}
makeArray(repeating: "knock", numberOfTimes: 4)
  1. 泛型类型
swift 复制代码
struct Stack<Element> {
    private var items: [Element] = []
    mutating func push(_ item: Element) { items.append(item) }
    mutating func pop() -> Element { items.removeLast() }
}
  1. where 约束
swift 复制代码
func anyCommonElements<T: Sequence, U: Sequence>(_ lhs: T, _ rhs: U) -> Bool
where T.Element: Equatable, T.Element == U.Element
{
    for lhsItem in lhs {
        for rhsItem in rhs {
            if lhsItem == rhsItem { return true }
        }
    }
    return false
}
anyCommonElements([1, 2, 3], [3])   // true

总结与实战建议

  1. Swift 的安全体现在:

    • 变量必须初始化;
    • 类型转换显式;
    • 可选型强制处理;
    • 数组越界直接运行时错误。

    写 Swift 会"被迫"把空值、边界、异常都考虑到,这恰恰减少了线上崩溃。

  2. 值类型优先思维:

    官方鼓励先用 struct,需要继承、共享状态、deinit 时才用 class

    在 UIKit / SwiftUI 里,Model 层大量采用 struct + let 保证数据流单向不可变。

  3. 协议导向编程:

    不同于 Java 的接口,Swift 协议可以带默认实现、关联类型、泛型 where 约束。

    利用 extension 给系统类型(如 IntString)追加协议,可写出极度简洁的 DSL。

  4. 并发模型:

    async/await + actor 让回调地狱消失,同时比 GCD 更容易推理执行顺序。

    注意:

    • 老项目混用 GCD 时,可用 Task { ... } 桥接;
    • 大量 CPU 密集任务,仍然使用 GCD 全局队列或 Task.detached
  5. 实战踩坑小贴士:

    • 闭包循环引用:捕获 self 时别忘 [weak self]
    • 枚举关联值无法自动 Equatable,需要手写或 enum MyEnum: Equatable
    • 泛型约束复杂时,优先用 where 子句而不是层层嵌套 <T: A & B & C>,可读性更好。
相关推荐
HarderCoder3 小时前
SwiftUI Binding 深坑指南:为什么 `Binding(get:set:)` 会让你的视图疯狂重绘?
swift
QWQ___qwq1 天前
My Swift笔记
swift
小蕾Java2 天前
IDEA快速上手指南!
java·intellij-idea·swift
山顶夕景3 天前
【LLM】基于ms-Swift大模型SFT和RL的训练实践
大模型·微调·swift·强化学习
HarderCoder4 天前
SwiftUI redraw 机制全景解读:从 @State 到 Diffing
swift
pixelpilot4 天前
Nimble:让SwiftObjective-C测试变得更优雅的匹配库
开发语言·其他·objective-c·swift
大熊猫侯佩4 天前
张真人传艺:Swift 6.2 Actor 隔离协议适配破局心法
swiftui·swift·apple
Dream_Ji6 天前
Swift入门(二 - 基本运算符)
服务器·ssh·swift
HarderCoder7 天前
Swift 6.1 `withTaskGroup` & `withThrowingTaskGroup` 新语法导读
ios·swift