Swift 快速上手

变量

/* 常量 */
let MAX = 100
let MIN = 1

/* 变量 */
var count = 0

/* 带类型标注 */
let name: String = "张三"
var age: Int = 18

/* 多变量声明 */
var x = 0.0, y = 0.0, z = 0.0

/* 类型推断 */
/* String */
var message = "Hello, Swift!"

/* 可空类型 */
var optionalName: String? = nil

流程控制

IF

if age >= 18 {
  print("成年人")
} else {
  print("未成年人")
}

if count < MIN {
  print("count 小于 MIN")
}
else if count == MIN {
  print("count 等于 MIN")
}
else if count >= 5 {
  print("count 大于等于 5")
}
else if count <= 10 {
  print("count 小于等于 10")
}
else if count != 11 {
  print("count 不等于 11")
}
else if count > MAX {
  print("count 大于 MAX")
}

if name == "张三" && age == 18 {
  print("张三是18岁")
}
if name == "李四" || age == 20 {
  print("名字是李四或者年龄是20")
}
if !(name == "张三") {
  print("名字不是张三")
}

Switch

switch count {
case MIN:
  print("count 等于 MIN")
case 5...10:
  print("count 大于等于 5 小于等于 10")
case 11:
  print("count 等于 11")
case let n where n % 2 == 0:
  print("count 是偶数")
case 12, 13, 14:
  print("count 是 12, 13, 14 中的一个")
default:
  print("其他情况")
}

守卫语句

if let unwrappedName = optionalName {
  /* 值仅在此花括号内有效 */
  print("可选值有值:\(unwrappedName)")
} else {
  /* 无值处理 */
  print("可选值为空")
}

guard let unwrappedName = optionalName else {
  /* 无值处理 需要中断执行 否则后续代码会继续执行 */
  print("可选值为空")
  return
}
/* 值在 guard 后的花括号剩余范围中有效 */
print("可选值有值:\(unwrappedName)")

循环

/* [1, 5] */
for i in 1...5 {
  print(i)
}

/* [0, 5) */
for i in 0..<5 {
  print(i)
}

/* [0, 5] */
for i in ...5 {
  print(i)
}

/* 步长为2 不包含结束值 */
for n in stride(from: 1, to: 5, by: 2) {
  print(n)
}

/* 步长为2 包含结束值 */
for n in stride(from: 1, through: 5, by: 2) {
  print(n)
}

/* 遍历字符串字符 */
for c in "Hello Swift" {
  print(c) // 'H'、'e'、...
}

/* 忽略循环变量 */
for _ in 1...3 {
  print("Hello")
}

/* 跳过循环 */
for n in 0...100 {
  if n % 2 == 0 {
    continue
  }
  print(n)
}

/* 提前退出循环 */
for n in 1...10 {
  if n == 5 {
    break
  }
  print(n)
}

/* 无限循环 */
while true {
  print("无限循环")
}

/* 有限循环 */
while count < 10 {
  count += 1
  print(count)
}

/* 至少执行一次 */
repeat {
  count -= 1
  print(count)
} while count > 0

函数

/* 基本函数 */
func printHello() {
  print("Hello, Swift!")
}
printHello()

/* 带参数函数 */
func printHello(name: String) {
  print("Hello, \(name)!")
}
printHello("World")

/* 带返回值函数 */
func getPrintContent() -> String {
  return "Hello, Swift!"
}
print(getPrintContent())

/* 带参数和隐式返回值函数 */
func getLogContent(name: String) -> String {
  "Hello, \(name)!"
}
print(getLogContent("World"))

/* 带多个参数函数 */
func add(a: Int, b: Int) -> Int {
  a + b
}
print(add(a: 5, b: 10))

/* 带多个返回值函数 */
func getAddResult(a: Int, b: Int) -> (Int, Int, Int) {
  return (a, b, a + b)
}
let addResult = getAddResult(a: 5, b: 10)
print("\(addResult.0) + \(addResult.1) = \(addResult.2)")

/* 带命名返回值函数 */
func getAddData(a: Int, b: Int) -> (first: Int, second: Int, sum: Int) {
  return (a, b, a + b)
}
let addData = getAddData(a: 5, b: 10)
print("\(addData.first) + \(addData.second) = \(addData.sum)")

/* 带别名参数函数 */
func go(from p1: Int, to p2: Int) {
  for i in p1...p2 {
    print("from \(p1) to \(p2) current in \(i)")
  }
}
go(from: 1, to: 5)

/* 可变参数函数 */
func addNumbers(_ numbers: Int...) -> Int {
  var sum = 0
  for number in numbers {
    sum += number
  }
  return sum
}
print(addNumbers(1, 2, 3, 4, 5))

/* 带输入输出参数函数 */
var sesason = "Spring"
func nextSeason(_ season: inout String) {
  switch season {
  case "Spring":
    season = "Summer"
  case "Summer":
    season = "Autumn"
  case "Autumn":
    season = "Winter"
  case "Winter":
    season = "Spring"
  default:
    season = "Unknown"
  }
}
print("当前季节:\(sesason)")
nextSeason(&sesason)
print("下一个季节:\(sesason)")

/* 可选参数与可空返回值函数 */
func getFirst(name: String?) -> String? {
  return name?.first
}
if let firstChar = getFirst(name: "张三") {
  print("名字的第一个字是:\(firstChar)")
} else {
  print("名字为空")
}

/* 函数作为参数 */
func computed(
  a: Int,
  b: Int,
  operate: (Int, Int) -> Int
) -> Int {
  return operate(a, b)
}
var sum = -1
/* 标准函数参数 */
sum = computed(a: 5, b: 10, operate: { (x: Int, y: Int) -> Int in
  return x + y
})
/* 当最后一个参数是函数时,允许尾随闭包 */
sum = computed(a: 5, b: 10) { (x: Int, y: Int) -> Int in
  return x + y
}
/* 自动推断类型 */
sum = computed(a: 5, b: 10, operate: { (x, y) in
  x + y
})
/* 简化参数,$0、$1 分别代表第一个和第二个输入参数,后续其他参数以此类推 */
sum = computed(a: 5, b: 10, operate: { $0 + $1 })
print("5 + 10 = \(sum)")

/* 函数闭包 */
func addNumber(_ n: Int) -> (Int) -> (Int) -> Int {
  func addInner(_ m: Int) -> (Int) -> Int {
    func addFinal(_ p: Int) -> Int {
      return n + m + p
    }
    return addFinal
  }
  return addInner
}
let add1 = addNumber(1)
let add2 = add1(2)
print(add2(3)) // 1 + 2 + 3 = 6

泛型

/* 交换 int 元组 */
func swapIntTuple(_ tuple: (Int, Int)) -> (Int, Int) {
  return (tuple.1, tuple.0)
}

/* 交换 double 元组 */
func swapDoubleTuple(_ tuple: (Double, Double)) -> (Double, Double) {
  return (tuple.1, tuple.0)
}

/* 交换元组而不在乎类型 */
func swapGenericTuple<T>(_ tuple: (T, T)) -> (T, T) {
  return (tuple.1, tuple.0)
}

/* 两个数值类型相加 将 N 类型约束为 Numberic 数字类型 */
func add<N: Numeric>(_ a: N, _ b: N) -> N {
  a + b
}

/* 返回值隐藏类型,但对编译器已知 */
func getView() -> some Numeric {
// 等价于 func getView<ReturnValueType>() -> ReturnValueType where ReturnValueType: Numeric
  2
}

结构体

/* 结构体是值类型 */
struct Person<V> {
  var name: String
  /* 结构体默认值 */
  var age: Int = 0

  /* 延迟属性 在首次访问时才创建 */
  lazy var bigData = Array(repeating: 0, count: 1000)

  /* 计算属性 根据其他值计算出而不是存储值 */
  var msg: String { return "name: \(name)\nage: \(age)" }

  /* 接收泛型 */
  var data: [[V]] = []

  /* 定义下标访问 */
  subscript(row: Int, col: Int) -> V {
    get { return data[row][col] }
    set { data[row][col] = newValue }
  }

  /* 嵌套内部类型 */
  struct Children {
    var name: String
  }

  /* 结构体构造函数 */
  init(_ name: String) {
    self.name = name
  }

  /* 结构体方法 */
  func say(_ msg: String) -> Void {
    print("\(self.name) say \(msg)")
  }

  /* 结构体变异方法 修改结构体属性 */
  mutating func nextAge() -> Int {
    self.age += 1
    return self.age
  }

  /* 结构体变异方法 修改结构体自身 */
  mutating func changePerson(_ name: String) -> Self {
    self = Person(name)
    return self
  }
}

/* 类是引用类型 */
class Person<V> {
  var name: String
  /* 内部类默认值 */
  var age: Int = 0

  /* 接收泛型 */
  var data: [V] = []

  /* 类构造函数 */
  init(name: String) {
    self.name = name
  }

  /* 便利构造器 简化初始逻辑 */
  convenience init(name: String, age: Int){
    self.init(name: name)
    self.age = age
  }

  /* 属性观察器 */
  var score: Int = 0 {
    willSet { print("Score 将变为 \(newValue)") }
    didSet { print("Score 先前是 \(oldValue)") }
  }

  /* 下标 */
  subscript(index: Int) -> V? {
    return index >= 0 && index < data.count ? data[index] : nil
  }

  /* 静态属性 */
  static var count: Int = 0
  /* 静态方法 */
  static func setCounter(){
    count += 1
  }

  /* 析构函数 */
  deinit{
    print("\(name)被释放")
  }
}

/* 类继承 */
class Father {
  var name: String
  var age: Int

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

  func info() -> String {
    return "name: \(name), age: \(age)"
  }

  /* 不允许被重写 */
  final func say() {
    print("hello")
  }

}
/* 子类 final 不允许再继承了 */
final class Son: Father {
  var school: String

  init(name: String, age: Int, school: String) {
    self.school = school
    super.init(name: name, age: age)
  }

  /* 重写父类方法 */
  override func info() -> String {
    return super.info() + ", school: \(school)"
  }
}

class Node {
  /* 父节点强引用子节点 */
  var children: Node?
  /* 子节点弱引用父节点 避免循环引用 */
  weak var parent: Node?
}

枚举

enum Day {
  /* 枚举值会自动增加 */
  case sunday     = 0
  case monday    // 1
  case tuesday   // 2
  case wednesday // 3
  case thursday  // 4
  case friday    // 5
  case saturday  // 6
}

/* 在确定类型的情况下 可以省略类型名 直接使用 .xxx 语法 */
let casualWorkday: Day = .friday // 等价于 Day.friday

/* 从原始值初始化 */
enum Direction: String {
  case north = "N"
  case south = "S"
  case east  = "E"
  case west  = "W"
}
let direction1 = Direction(rawValue: "N") // Optional(Direction.north)
let direction2 = Direction(rawValue: "X") // nil
let north = Direction.north.rawValue      // "N"

/* 关联值枚举 */
enum Barcode {
  case upc(Int, Int, Int, Int)
  case qrCode(String)
}
var productBarcode = Barcode.upc(8, 85909, 51226, 3)
switch productBarcode {
case .upc(let numberSystem, let manufacturer, let product, let check):
  print("UPC: \(numberSystem), \(manufacturer), \(product), \(check)")
case .qrCode(let code):
  print("QR Code: \(code)")
}

/* 计算属性 */
enum Power {
  case NONE     = 0
  case READ     = 4
  case WRITE    = 2
  case EXECUTE  = 1

  var name: String {
    switch self {
      case .NONE:     return "none"
      case .READ:     return "read"
      case .WRITE:    return "write"
      case .EXECUTE:  return "execute"
    }
  }
}

/* 可迭代 */
/* CaseIterable 是一个迭代协议,允许访问 allCases 获取枚举所有值数组 */
enum Season: CaseIterable {
  case winter
  case spring
  case summer
  case fall
}
for season in Season.allCases {
  print(season)
}

/* 实例方法 */
enum Traffic {
  case light
  case heavy

  /* 变异方法 允许改变枚举实例值,需要使用 mutating 标记 */
  mutating func reportAccident() {
    self = .heavy
  }
}
var currentTraffic: Traffic = .light
currentTraffic.reportAccident()

协议

/* 协议类似抽象类 但允许被类、结构体、枚举等实现 */
protocol ExampleProtocol {
  var simpleDescription: String { get }
  mutating func adjust()
}

class SimpleClass: ExampleProtocol {
  var simpleDescription: String = "A very simple class."
  var anotherProperty: Int = 69105
  func adjust() {
    simpleDescription += "  Now 100% adjusted."
  }
}
var a = SimpleClass()
a.adjust()
let aDescription = a.simpleDescription

struct SimpleStructure: ExampleProtocol {
  var simpleDescription: String = "A simple structure"
  mutating func adjust() {
    simpleDescription += " (adjusted)"
  }
}
var b = SimpleStructure()
b.adjust()
let bDescription = b.simpleDescription

扩展

/* 扩展可以为以现有的类、结构体、枚举或协议增加新的属性和方法 */
extension Int {
  // 扩展 Int 实现新功能
}

extension Int: ExampleProtocol {
  // 扩展 Int 实现 ExampleProtocol 协议
  var simpleDescription: String {
    return "The number \(self)"
  }
  mutating func adjust() {
    self += 42
  }
}

extension ExampleProtocol {
  func adjust(){
    // 扩展协议,进行默认实现
  }
}

错误处理

/* 任何实现了 Error 协议的枚举都被视为错误 */
enum PrinterError: Error {
  case outOfPaper
  case noToner
  case onFire
}

/* 函数可以使用 throws 关键字标记,表明它可能会抛出错误 */
func send(job: Int, toPrinter printerName: String) throws -> String {
  if printerName == "Never Has Toner" {
    throw PrinterError.noToner
  }
  return "Job sent"
}

do {
  let response = try send(job: 1040, toPrinter: "Test")
  print(response)
}
/* 统一处理错误 */
catch {
  print(error)
}

do {
  let response = try send(job: 1040, toPrinter: "Test")
  print(response)
}
catch PrinterError.onFire {
  // 单独处理某个错误
}
catch let e as PrinterError {
  // 处理 .onFire 以外的所有 PrinterError 枚举错误
}
/* 统一处理错误 */
catch {
  print(error)
}

/* 将结果转换为可选的 如果错误发生,则会被抛弃,结果变为 nil */
let success = try? send(job: 1884, toPrinter: "Mergenthaler")

/* 退出前执行 无论是否抛出错误 */
func executeTask() {
  print("执行任务开始")
  defer {
    print("任务结束,进行清理工作")
  }
  print("处理中...")
}
executeTask()

异步

/* async 用于标记异步函数 */
func fetch(from server: String) async -> Int {
  if server == "http://localhost" {
      return 200
  }
  return 500
}

/* 在异步函数前使用 await 关键字调用 按定义顺序依次执行 */
func fetchUsername(from server: String) async -> String {
  let fetchURL = await fetch(from: server)
  let userID = await fetch(from: fetchURL)
  if userID == 500 {
    return "John Appleseed"
  }
  return "Guest"
}

/* 使用 async let 会让多个异步任务并发执行 而不是按定义顺序依次执行 但在函数执行完毕退出时,必须 await 所有 async let */
func fetchLogin(account: String, pwd: String) async -> String {
  async let loginReq = fetch(from: "http://localhost/login?account=\(account)&pwd=\(pwd)")
  async let userIDReq = fetch(from: "http://localhost/userID?account=\(account)")

  let userID = await userIDReq
  async let usernameReq = fetchUsername(from: "http://localhost/username?userID=\(userID)")

  let login = await loginReq
  let username = await usernameReq

  return "loginResult: \(login), userIDResult: \(userID), usernameResult: \(username)"
}

模块化

Project/
  |- Package.swift
  |- Sources/
    |- Network/
      |- Request.swift
      |- Response.swift
      |- PreHandle.swift
      |- lastHandle.swift
    |- UI/
      |- HomeView.swift
      |- LoginView.swift
    |- Model/
      |- User.swift
      |- Article.swift
    |- APP/
      |- main.swift
// Package.swift
import PackageDescription

let package = Package(
    name: "Project",
    platforms: [.iOS(.v15)],
    products: [
        .executable(name: "App", targets: ["App"])
    ],
    targets: [
        .target(name: "Model"),
        .target(name: "Network", dependencies: ["Model"]),
        .target(name: "UI", dependencies: ["Network"]),
        .executableTarget(name: "App", dependencies: ["UI"])
    ]
)
// App → UI → Network -> Model

// 扩模块暴露 可继承重写
open class Person {}

// 跨模块暴露 不可继承重写
public struct User {}

// 仅在当前模块内暴露 默认
internal class LoginService {}

// 仅当前文件暴露
fileprivate struct LoginDTO {}

// 仅当前作用域暴露
private var n: String

Swift 快速上手
https://www.inksha.com/archives/swift-kuai-su-shang-shou
作者
inksha
发布于
2025年12月29日
许可协议