第三章:Swift语言基础(二)——运算符、字符串与可选类型
好,咱们接着往下走。上一章我们把变量、常量、基本数据类型都捋了一遍,算是打好了地基。这一章要聊的,是Swift里几个特别“日常”但又特别容易踩坑的东西——运算符、字符串处理,还有那个让新手又爱又恨的可选类型。
我个人觉得,可选类型是Swift区别于其他语言最显著的一个特征。你想想看,一个变量可能“有值”,也可能“没值”,这在OC或者Java里通常用nil或者null来表示,但一不小心就会崩溃。Swift用了一套更安全的机制来处理它。嗯,咱们慢慢聊。
3.1 基本运算符:不只是加减乘除
运算符这块,大部分跟其他语言差不多。但有几个细节,我建议你留意一下。
3.1.1 赋值运算符与算术运算符
let a = 10
var b = 5
b = a // b 现在是 10
let sum = a + b // 20
let diff = a - b // 0
let product = a * b // 100
let quotient = a / b // 1(整数除法,结果还是整数)
这里有个坑:整数除法会直接截断小数部分。我在项目中遇到过好几次,新手算平均值时直接用Int相除,结果丢了精度。如果你想要小数结果,记得把操作数转成Double。
let exact = Double(a) / Double(b) // 1.0,但这里a和b相等所以不明显
let c = 7, d = 3
let result = Double(c) / Double(d) // 2.3333...
3.1.2 比较运算符与三元运算符
比较运算符返回Bool值,这个没什么好说的。但三元运算符 ? : 我建议你谨慎使用——不是说不能用,而是嵌套多了代码可读性会变得很差。
let age = 20
let canDrive = age >= 18 ? "可以开车" : "再等等"
这种简单的场景用三元运算符很清爽。但如果你写成 a ? b ? c : d : e 这种,相信我,过两周你自己都看不懂。
3.2 字符串插值与拼接
字符串操作在iOS开发里太频繁了。显示用户名字、拼接网络请求参数、格式化日志……几乎每个页面都会用到。
3.2.1 字符串拼接
最直接的方式就是用 + 号:
let firstName = "张"
let lastName = "三"
let fullName = firstName + lastName // "张三"
也可以用 += 来追加:
var greeting = "你好"
greeting += ",世界" // "你好,世界"
3.2.2 字符串插值
这个才是Swift的亮点。用 \() 把变量或表达式直接嵌入字符串中:
let name = "小明"
let age = 25
let message = "我叫\(name),今年\(age)岁"
// 输出:"我叫小明,今年25岁"
插值里甚至可以放表达式:
let price = 9.9
let count = 3
let total = "总价:\(price * Double(count)) 元"
3.3 可选类型(Optional)详解
好,重头戏来了。可选类型是Swift用来表示“可能有值,也可能没值”的一种包装。说白了,就是一个盒子——盒子里可能有东西,也可能是空的。
3.3.1 为什么需要可选类型?
你想想看,一个变量如果可能为nil,那你在使用它之前必须检查。OC里你忘了检查,直接给nil发消息,虽然大部分情况下不会崩溃,但一旦遇到特殊情况……嗯,我曾经在定位一个闪退问题时,查了半天发现是一个NSString没初始化就拿来拼接了。
Swift从语言层面解决了这个问题:普通变量不允许为nil,只有可选类型才能为nil。
var normalString: String = "Hello"
// normalString = nil // 编译错误!
var optionalString: String? = "Hello"
optionalString = nil // 没问题
看到那个问号 ? 了吗?它就是可选类型的标志。
3.3.2 可选类型的本质
可选类型其实是一个枚举:
enum Optional<Wrapped> {
case none // 没有值
case some(Wrapped) // 有值,包装了实际的值
}
所以 String? 本质上就是 Optional<String>。你不需要手动写这个枚举,但理解它的结构有助于你理解后面的解包操作。
3.4 可选绑定与强制解包
既然值被“包装”起来了,那怎么取出来用呢?有两种方式:强制解包和可选绑定。
3.4.1 强制解包(不建议滥用)
用 ! 来强制取出值:
var maybeNumber: Int? = 42
let definitelyNumber = maybeNumber! // 42
但如果 maybeNumber 是nil,这行代码会直接崩溃。我在刚学Swift时就犯过这个错——从服务器取了个字段,以为一定有值,结果后台返回了null,app直接闪退。
! 是安全的。其他情况,尽量别用。
3.4.2 可选绑定(推荐方式)
用 if let 或 guard let 来安全地解包:
var userName: String? = "张三"
// if let 方式
if let name = userName {
print("用户名为:\(name)")
} else {
print("用户名为空")
}
// guard let 方式(常用于函数开头)
func greet(user: String?) {
guard let name = user else {
print("没有用户,无法打招呼")
return
}
print("你好,\(name)")
}
if let 和 guard let 的区别在于:if let 只在花括号内能使用解包后的值;guard let 则让解包后的值在后续代码中都可以使用,但必须搭配 return、break 等语句提前退出。
我个人更倾向于用 guard let,因为它能减少嵌套层级,让代码更扁平。你想想看,如果连续解包三个可选值,用 if let 会变成三层嵌套,而 guard let 只需要三个连续的守卫语句。
3.4.3 多个可选绑定
Swift允许在一个 if let 中同时解包多个值:
let age: Int? = 25
let city: String? = "北京"
if let a = age, let c = city {
print("年龄:\(a),城市:\(c)")
}
还可以加上条件判断:
if let a = age, a > 18 {
print("已成年")
}
3.5 nil合并运算符
这个运算符 ?? 是我在项目中用得最多的一个。它的作用很简单:如果可选值有值,就取出来;如果为nil,就使用一个默认值。
let nickname: String? = nil
let displayName = nickname ?? "游客"
// displayName 是 "游客",因为 nickname 为 nil
let realName: String? = "李四"
let showName = realName ?? "游客"
// showName 是 "李四"
说白了,?? 就是 if let 的简化版。上面这个例子如果用 if let 写:
let displayName2: String
if let name = nickname {
displayName2 = name
} else {
displayName2 = "游客"
}
你看,三行代码变成了一行。而且 ?? 可以链式使用:
let a: String? = nil
let b: String? = nil
let c: String? = "最终值"
let result = a ?? b ?? c ?? "兜底值"
// result 是 "最终值"
?? 给UILabel赋值,但忘了考虑空字符串的情况。比如用户昵称可能是空字符串 "",它不是nil,所以 ?? 不会触发默认值,结果界面上就显示了一个空标签。所以,?? 只处理nil,不处理空字符串。如果你需要同时处理nil和空字符串,建议用 if let 加额外判断。
3.6 综合示例:用户信息展示
咱们把这一章的知识点串起来,写一个简单的用户信息展示逻辑:
// 模拟从服务器获取的数据(可能为nil)
let serverNickname: String? = "小明"
let serverAge: Int? = nil
let serverCity: String? = "上海"
// 使用 nil 合并运算符提供默认值
let displayNickname = serverNickname ?? "匿名用户"
let displayAge = serverAge ?? 0
let displayCity = serverCity ?? "未知城市"
// 使用字符串插值拼接展示信息
let profile = """
用户信息:
昵称:\(displayNickname)
年龄:\(displayAge)
城市:\(displayCity)
"""
print(profile)
// 输出:
// 用户信息:
// 昵称:小明
// 年龄:0
// 城市:上海
这个例子虽然简单,但涵盖了可选类型、nil合并运算符、字符串插值这几个核心知识点。你在实际开发中,几乎每天都会写类似的代码。
3.7 本章小结
这一章的内容,说白了就是三件事:
- 运算符:注意整数除法的截断,三元运算符别嵌套太深
- 字符串:多用插值少拼接,代码更清晰
- 可选类型:这是Swift的“护身符”,用
if let或guard let安全解包,用??提供默认值,尽量别用强制解包
下一章我们会聊集合类型——数组、字典、集合。这些东西在管理数据时特别有用。到时候我会分享一些我在处理列表数据时的经验,咱们下次见。