
1. 引言在 Swift 編程語言中常量是構建安全、可預測代碼的基礎。與變量不同常量一旦賦值便不可更改這不僅能防止意外修改還能讓代碼的意圖更加清晰。本文將深入講解 Swift 常量的定義、使用場景以及最佳實踐并通過豐富的代碼實例幫助你快速掌握。2. 什么是常量常量是指在程序運行過程中值保持不變的量。Swift 使用let關鍵字來聲明常量。一旦為常量賦值就不能再修改它的值。這種不可變性是 Swift 類型安全體系的重要組成部分。與變量使用var聲明相比常量具有以下優(yōu)勢安全性防止代碼在無意中修改重要數(shù)據(jù)??勺x性明確告訴閱讀者該值不會變化降低理解成本。性能優(yōu)化編譯器可以對常量進行更多優(yōu)化提升運行效率。3. 常量的基本用法使用let關鍵字聲明常量語法非常簡單let constantName: Type value其中類型標注: Type是可選的Swift 支持類型推斷。下面是一些基本示例// 聲明一個整數(shù)常量 let maxAttempts 5 // 聲明一個字符串常量 let appName MySwiftApp // 聲明一個浮點常量 let pi 3.14159 // 顯式指定類型 let isEnabled: Bool true // 打印常量值 print(應用名稱\(appName)) print(最大嘗試次數(shù)\(maxAttempts))4. 常量的類型推斷Swift 強大的類型推斷機制允許你在聲明常量時省略類型標注。編譯器會根據(jù)賦值的字面量自動推斷常量的類型// 整數(shù)類型推斷為 Int let age 25 // 浮點數(shù)類型推斷為 Double let height 1.75 // 字符串類型推斷為 String let city 北京 // 布爾類型推斷為 Bool let isLoggedIn true // 使用 type(of:) 查看推斷出的類型 print(type(of: age)) // 輸出Int print(type(of: height)) // 輸出Double print(type(of: city)) // 輸出String print(type(of: isLoggedIn)) // 輸出Bool5. 常量的不可變性常量的核心特性是不可變性。一旦賦值任何試圖修改常量的操作都會導致編譯錯誤。下面通過代碼演示let fixedValue 100 // 下面的代碼會報錯Cannot assign to value: fixedValue is a let constant // fixedValue 200 // 正確的做法如果需要可變值使用 var var mutableValue 100 mutableValue 200 print(可變值\(mutableValue))編譯器會在編譯階段就攔截對常量的修改這有助于在開發(fā)早期發(fā)現(xiàn)潛在問題。6. 常量與變量的選擇在 Swift 開發(fā)中一個重要的原則是優(yōu)先使用常量只有在值確實需要變化時才使用變量。下面通過對比示例來說明// 不推薦使用變量聲明不會變化的值 var userName Alice var maxRetryCount 3 // 推薦使用常量聲明不會變化的值 let userName Alice let maxRetryCount 3 // 需要變化的值才使用變量 var currentScore 0 currentScore 10 print(當前得分\(currentScore))遵循這一原則可以讓代碼更加健壯減少因意外賦值導致的 bug。7. 常量的作用域常量可以定義在全局作用域、函數(shù)作用域或類/結構體內(nèi)部。不同作用域的常量具有不同的生命周期和訪問范圍// 全局常量 let globalConstant 全局常量 func demoScope() { // 函數(shù)內(nèi)局部常量 let localConstant 局部常量 print(localConstant) print(globalConstant) // 可以訪問全局常量 } class MyClass { // 類型屬性類常量 static let classConstant 類常量 // 實例屬性實例常量 let instanceConstant: String init(value: String) { self.instanceConstant value } } demoScope() print(MyClass.classConstant) let obj MyClass(value: 實例常量) print(obj.instanceConstant)8. 常量與集合類型當常量是數(shù)組、字典或集合時需要注意常量本身不可重新賦值但其內(nèi)部元素是否可變?nèi)Q于集合的類型。Swift 中的Array、Dictionary和Set是值類型因此用let聲明的集合其元素也不可修改// 常量數(shù)組元素不可修改 let fruits [蘋果, 香蕉, 橙子] // fruits.append(葡萄) // 錯誤Cannot use mutating member on immutable value // fruits[0] 西瓜 // 錯誤Cannot assign through subscript // 常量字典鍵值對不可修改 let scores [數(shù)學: 95, 語文: 88] // scores[英語] 90 // 錯誤 // 常量集合 let uniqueNumbers: SetInt [1, 2, 3] // uniqueNumbers.insert(4) // 錯誤 // 如果需要可變集合使用 var var mutableFruits [蘋果, 香蕉] mutableFruits.append(葡萄) print(mutableFruits)9. 常量與引用類型當常量指向的是引用類型如類實例時常量本身不可重新賦值但通過該常量可以修改對象的屬性或調(diào)用修改方法。這是因為引用類型是共享的class Counter { var count 0 } // 常量指向類實例 let counter Counter() counter.count 10 // 允許修改對象的屬性 print(計數(shù)\(counter.count)) // counter Counter() // 錯誤Cannot assign to value: counter is a let constant // 對比結構體是值類型let 聲明的結構體屬性不可修改 struct Point { var x: Int var y: Int } let point Point(x: 1, y: 2) // point.x 5 // 錯誤Cannot assign to property: point is a let constant10. 常量與可選類型常量同樣可以聲明為可選類型??蛇x常量在賦值前默認為nil賦值后不可再修改// 聲明可選常量 let optionalValue: Int? nil // optionalValue 10 // 錯誤Cannot assign to value: optionalValue is a let constant // 在初始化時直接賦值 let initializedOptional: String? Hello print(initializedOptional ?? 默認值) // 可選常量配合 if let 使用 let username: String? SwiftUser if let name username { print(用戶名\(name)) } else { print(用戶名為空) }11. 常量與元組元組可以將多個值組合成一個復合值。使用let聲明的元組其元素同樣不可修改// 聲明元組常量 let coordinates (x: 10, y: 20) print(x: \(coordinates.x), y: \(coordinates.y)) // 元組解構 let (width, height) (1920, 1080) print(分辨率\(width) x \(height)) // 元組作為函數(shù)返回值 func getMinMax() - (min: Int, max: Int) { return (1, 100) } let result getMinMax() print(最小值\(result.min)最大值\(result.max)) // 修改元組元素會報錯 // coordinates.x 30 // 錯誤Cannot assign to property: coordinates is a let constant12. 常量與計算屬性雖然常量本身不可變但你可以使用計算屬性來動態(tài)獲取值。計算屬性不存儲值而是每次訪問時計算struct Circle { let radius: Double // 計算屬性每次訪問時計算 var area: Double { return Double.pi * radius * radius } var circumference: Double { return 2 * Double.pi * radius } } let circle Circle(radius: 5.0) print(面積\(circle.area)) print(周長\(circle.circumference)) // 計算屬性是只讀的不能賦值 // circle.area 100 // 錯誤Cannot assign to property: area is a get-only property13. 常量與函數(shù)參數(shù)在 Swift 中函數(shù)參數(shù)默認是常量。這意味著在函數(shù)體內(nèi)不能修改參數(shù)的值func greet(name: String) { // name 是常量不能修改 // name 新名字 // 錯誤Cannot assign to value: name is a let constant print(你好\(name)) } // 如果需要修改參數(shù)使用 inout 參數(shù) func increment(_ number: inout Int) { number 1 } var count 10 increment(count) print(遞增后\(count)) // 調(diào)用函數(shù) greet(name: Swift)14. 常量與閉包閉包可以捕獲常量。被捕獲的常量在閉包內(nèi)保持其值即使閉包在常量作用域之外被調(diào)用func makeIncrementer(amount: Int) - () - Int { var total 0 // 捕獲 amount 常量 return { total amount return total } } let incrementByTen makeIncrementer(amount: 10) print(incrementByTen()) // 輸出10 print(incrementByTen()) // 輸出20 print(incrementByTen()) // 輸出30 // 常量捕獲示例 let baseValue 100 let addBase: (Int) - Int { value in return value baseValue } print(addBase(50)) // 輸出15015. 常量與枚舉枚舉的關聯(lián)值和原始值經(jīng)常與常量配合使用。枚舉本身是值類型用let聲明的枚舉常量不可修改enum Direction { case north, south, east, west } enum StatusCode: Int { case success 200 case notFound 404 case serverError 500 } // 枚舉常量 let direction Direction.north let status StatusCode.success // 使用 switch 匹配枚舉 switch direction { case .north: print(向北) case .south: print(向南) case .east: print(向東) case .west: print(向西) } // 枚舉原始值 print(狀態(tài)碼\(status.rawValue)) // 枚舉關聯(lián)值 enum Barcode { case upc(Int, Int, Int, Int) case qrCode(String) } let 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)) }16. 常量與泛型在泛型編程中常量同樣扮演重要角色。泛型函數(shù)或類型中的常量可以保持類型安全// 泛型函數(shù)中的常量 func findMaxT: Comparable(in array: [T]) - T? { guard let first array.first else { return nil } var maxValue first for item in array { if item maxValue { maxValue item } } return maxValue } let numbers [3, 7, 1, 9, 5] if let maxNumber findMax(in: numbers) { print(最大值\(maxNumber)) } let strings [apple, banana, cherry] if let maxString findMax(in: strings) { print(最大字符串\(maxString)) } // 泛型結構體中的常量 struct StackElement { private var items: [Element] [] mutating func push(_ item: Element) { items.append(item) } mutating func pop() - Element? { return items.popLast() } var count: Int { return items.count } } var stack StackInt() stack.push(1) stack.push(2) stack.push(3) print(棧元素個數(shù)\(stack.count)) print(彈出\(stack.pop() ?? -1))17. 常量與協(xié)議協(xié)議中可以使用常量要求但通常通過計算屬性或靜態(tài)屬性來實現(xiàn)。下面展示如何在協(xié)議中使用常量protocol Vehicle { var maxSpeed: Int { get } var name: String { get } } struct Car: Vehicle { // 使用常量滿足協(xié)議要求 let maxSpeed: Int let name: String } struct Bicycle: Vehicle { let maxSpeed: Int let name: String } let car Car(maxSpeed: 200, name: 跑車) let bicycle Bicycle(maxSpeed: 30, name: 自行車) func describe(vehicle: Vehicle) { print(\(vehicle.name) 的最高速度是 \(vehicle.maxSpeed) km/h) } describe(vehicle: car) describe(vehicle: bicycle) // 協(xié)議中的靜態(tài)常量 protocol AppConfig { static var appName: String { get } static var version: String { get } } struct DevelopmentConfig: AppConfig { static let appName DevApp static let version 1.0.0-beta } struct ProductionConfig: AppConfig { static let appName ProductionApp static let version 1.0.0 } print(開發(fā)環(huán)境\(DevelopmentConfig.appName) \(DevelopmentConfig.version)) print(生產(chǎn)環(huán)境\(ProductionConfig.appName) \(ProductionConfig.version))18. 常量與錯誤處理在錯誤處理中常量常用于定義錯誤碼和錯誤信息確保錯誤處理的穩(wěn)定性和可讀性// 定義錯誤類型 enum NetworkError: Error { case badURL case timeout case serverError(code: Int) } // 使用常量定義錯誤信息 let errorMessages: [NetworkError: String] [ .badURL: 無效的 URL, .timeout: 請求超時, .serverError(code: 500): 服務器內(nèi)部錯誤 ] func fetchData(from urlString: String) throws - String { // 使用常量校驗 URL let validURLPrefix https:// guard urlString.hasPrefix(validURLPrefix) else { throw NetworkError.badURL } // 模擬網(wǎng)絡請求 let simulatedResponse 模擬數(shù)據(jù) return simulatedResponse } // 錯誤處理示例 do { let data try fetchData(from: https://example.com) print(獲取數(shù)據(jù)\(data)) } catch NetworkError.badURL { print(錯誤無效的 URL) } catch NetworkError.timeout { print(錯誤請求超時) } catch { print(未知錯誤\(error)) }19. 常量與并發(fā)編程在 Swift 并發(fā)編程中常量對于保證線程安全尤為重要。不可變數(shù)據(jù)天然適合在多線程環(huán)境中共享import Foundation // 使用常量定義線程安全的配置 let threadSafeConfig [ timeout: 30, maxRetries: 3, enableLogging: true ] // 使用 DispatchQueue 模擬并發(fā)訪問 let queue DispatchQueue(label: com.example.concurrent, attributes: .concurrent) for index in 0..5 { queue.async { // 并發(fā)讀取常量是安全的