一、什么是 Swift 常量
在 Swift 中,常量使用 let 关键字声明,变量使用 var 关键字声明。常量一旦被赋值,就不能再被修改。这是 Swift 语言安全性的重要体现,也是官方推荐优先使用的声明方式。
swift
let maximumLoginAttempts = 10
var currentLoginAttempt = 0
上面的例子中,maximumLoginAttempts 是一个常量,值固定为 10;currentLoginAttempt 是变量,可以在后续逻辑中递增。
Swift 官方建议:优先使用
let,只有在确实需要修改值时才使用var。这样可以让编译器帮你发现意外的修改,也能让代码意图更清晰。
二、常量的声明与初始化
2.1 声明时直接赋值
swift
let pi = 3.14159
let appName = "MyApp"
let isDebugMode = false
Swift 具备类型推断能力,会根据右侧的值自动推断常量的类型,因此通常不需要显式写出类型。
2.2 显式指定类型
swift
let pi: Double = 3.14159
let appName: String = "MyApp"
let maxCount: Int = 100
当需要明确类型,或者初始值无法让编译器推断出期望类型时,可以显式标注类型。
2.3 先声明后初始化
常量允许先声明、后赋值,但只能赋值一次,并且在使用前必须完成初始化。
swift
let userName: String
if isDebugMode {
userName = "DebugUser"
} else {
userName = "Guest"
}
print(userName)
这种写法常用于根据条件决定常量值的场景。注意:一旦赋值后再次赋值,编译器会直接报错。
三、常量与变量的区别
| 对比项 | 常量 let | 变量 var |
|---|---|---|
| 是否可修改 | 不可修改 | 可修改 |
| 赋值次数 | 只能赋值一次 | 可多次赋值 |
| 使用建议 | 优先使用 | 需要变化时使用 |
| 编译期优化 | 更容易被优化 | 优化空间较小 |
从性能和可读性角度看,常量能让编译器做更多优化,也能减少多线程场景下的状态变化风险。
四、常量的类型与常见写法
4.1 基本类型常量
swift
let intValue: Int = 42
let doubleValue: Double = 3.14
let boolValue: Bool = true
let charValue: Character = "A"
let stringValue: String = "Swift"
4.2 集合类型常量
需要注意:let 修饰的集合常量,其引用不可变,但内部元素是否可变取决于集合类型本身。
swift
let numbers = [1, 2, 3]
// numbers.append(4) // 编译错误:Cannot use mutating member on immutable value
let dict = ["name": "Tom", "age": "18"]
// dict["gender"] = "male" // 编译错误
var mutableArray = [1, 2, 3]
mutableArray.append(4) // 正确,var 声明的数组可以修改
对于 Array、Dictionary、Set 这类值类型,let 声明的实例整体不可变,不能调用 mutating 方法。
4.3 元组常量
swift
let httpStatus = (code: 200, message: "OK")
print(httpStatus.code) // 200
print(httpStatus.message) // OK
4.4 可选类型常量
swift
let optionalName: String? = nil
let optionalAge: Int? = 18
if let age = optionalAge {
print("年龄是 \(age)")
}
五、常量与引用类型
当常量指向类实例时,let 只保证引用不变,对象内部属性仍然可以修改(前提是属性本身是 var)。
swift
class Person {
var name: String
init(name: String) {
self.name = name
}
}
let person = Person(name: "Tom")
person.name = "Jerry" // 正确:修改对象内部属性
// person = Person(name: "Lucy") // 编译错误:不能重新赋值常量引用
这是值类型与引用类型在常量语义上的关键差异,理解这一点可以避免很多误用。
六、常量在编译期优化中的作用
编译器可以对常量进行常量折叠(constant folding)、内联等优化。例如:
swift
let base = 10
let result = base * 2 + 5
print(result) // 编译器可能直接优化为 25
虽然 Swift 的优化细节依赖具体编译器和优化级别,但使用 let 表达不可变意图,确实有助于编译器进行更激进的分析与优化。
七、常见误区与最佳实践
- **误区一:常量只能存简单值。**常量可以存任意类型,包括结构体、类、闭包等。
- 误区二:let 声明的对象完全不可变。 对引用类型,
let只锁定引用,不锁定内部状态。 - **误区三:为了省事全部用 var。**这会丢失编译期检查,增加意外修改的风险。
推荐实践:
- 默认使用
let,需要修改时再改为var。 - 常量命名使用小驼峰,语义清晰,例如
maxRetryCount。 - 全局常量建议集中管理,避免散落在各处。
- 需要跨文件共享的常量,可使用
static let或命名空间结构体。
swift
struct AppConfig {
static let apiBaseURL = "https://api.example.com"
static let timeout: TimeInterval = 30
}
print(AppConfig.apiBaseURL)
八、总结
Swift 常量通过 let 声明,具备不可变性、类型安全和编译期优化等优势。掌握常量的声明方式、值类型与引用类型的差异,以及常见最佳实践,可以写出更安全、更清晰的 Swift 代码。日常开发中,养成"默认 let、按需 var"的习惯,是提升代码质量的第一步。