Swift中的"+" 与 "??"的优先级

前言

swift中, 我们要将几个String组合在一起是极其方便的,比如

第一种: 使用类似C++中的 "+" 运算符重载
let dog = "string1" + "_string2"
print(dog)

输出结果:
string1_string2
第二种: 使用Swift牛逼的插入法

又比如

let string2 = "string2"
let cat = "string1_\(string2)"
print(cat)

输出结果:
string1_string2
第三种,使用Swift的 append(_ other: String) 函数

再比如

let string2 = "string2"
var string1 = "string1_"
string1.append(string2)
print(string1)

输出结果:
string1_string2

以上三种方式,都可以达到我们想要的效果。

但是,我们今天聊的并不是怎么拼接Swift中的字符串, 而是Swift中的另一种常见的类型:可选类型(Optional Type)

可选类型

Swift中,可选类型是十分常见的类型之一。我们都知道,当我们定义一个可选类型是,其默认值就是nil,如

var optionalVariable: String?

可选类型在Swift会使我们更为方便地处理一些特殊情况,比如值不存在,可以使我们的Swift代码更加安全,因为强制拆包一个未赋予任何值的可选类型,必然Crash!!!, 如

var dogVariable: String?
print(dogVariable!) // 奔溃,报错,因为强制拆包一个没有值的可选类型

但是在Swift中,这种奔溃在编码前期,可以给我们更好安全保障,因为我们可以通过一个可选值,去判断我们接收的服务端返回字段是否存在,或者在一个计算方法中是否合理使用所定义的可选值,在前期我们就可以检测到数据是否合理,变量定义是否冗余,书写是否规范等

当然,我相信几乎所有的程序猿都不会说喜欢自己写的代码奔溃,故此,Swift也不是说专门定义一个可选的概念给你,却没有解决的办法,办法还是有的,比如

var rabbit: String?
// 通过提供一个默认值来防止奔溃,rabbit的值不存在(即为nil),就输出默认值
print(rabbit ?? "defaultValue") 

// 输出结果
defaultValue

再比如,我们可以使用 if let绑定来安全并合理使用可选值

var elephant: String?
// 使用 if let 来安全检查
if let value = elephant {
    print(value)
} else {
    print("not exist!")
}

// 输出结果:
not exist!

我们还可以使用判断是否为nil来检查

var eagle: String?
if eagle == nil {
    print("eagle does not exist!")
}

输出结果:
eagle does not exist!

除此之外,我们也可以使用 guard let 语句,用法和 if let 类似,这里不赘述。

下面我们讲的是第一种方式,使用可选默认值结合Swift的字符串拼接符 "+", 来判断哪个的优先级更高!可能到这里,有人就说了,这么简单的问题谁不明白?还用得着小题大做写一篇博客,还啰嗦了这么多?很好,非常好的疑惑以及问题,那么下面,首先,请尝试做下面这道题目

var value: String?
for _ in 1...3 {
    value = value ?? "default" + "-swift"
    print(value!)
}

好,第一次就做对上面这个题目的人,恭喜你,这篇文章你不需要继续看下去了。那么你的答案应该看下来是这个样子

default-swift
default-swift
default-swift

那么,错误的答案应该看起来是下面这个样子

default-swift
default-swift-swift
default-swift-swift-swift

剖析优先级 + 和 ??

从上面正确答案,其实我们已经可以看出 +优先级??优先级更高,因为,在for in的3次循环遍历中

表面上,

  • 第一次, value的值肯定不存在,为nil, 所以值应该是 default-swift

  • 第二次,value由于第一次已经赋值default-swift,所以理论上值应该变成 default-swift-swift

  • 第三次,value由于第二次已经赋值 default-swift-swift,所以理论上值应该变成 default-swift-swift-swift

实际上,由于优先级的原因( "+" > "??")

  • 第一次,value = value ?? "default" + "-swift", 先算??右边,所以value等于default-swift

  • 第二次,由于第一次,value的值为default-swift,不再为 nil, 所以值存在,值还是第一次的值default-swift

  • 第三次,由于第二次,value的值还是default-swift,不再为 nil, 所以值还是存在,值还是第二次的值default-swift

综上,遍历循环三次,就算每次遍历都将值赋予value, 但是由于优先级的原因,打印的值永远是第一次的默认值,也就是 ?? 右边的 "default" + "-swift"

现在,回想一下你的答案,正确与否?

然后,我们来想一下,在项目中是否会总是不经意间犯这样低级的错误,那么如果这种情况下,我们想优先使用 ??的话,必须必须必须要加一个 括号(),如下

var value: String?
for _ in 1...3 {
    value = (value ?? "default") + "-swift"
    print(value!)
}

输出结果:
default-swift
default-swift-swift
default-swift-swift-swift

所以,在项目中,如果遇到类似的运算符交叉混合运算的情况下,务必要弄清楚优先级,当然,实在是不知道优先级的情况下,最最最安全的做法就是加上括号(),这样就确保万无一失了。

补充

事实上,+优先级也比三目运算符? :要高,比如

var value: String?
for _ in 1...5 {
    value = value == nil ? "default1":"default2" + "-swift"
    print(value!)
}

输出结果为:
default1
default2-swift
default2-swift
default2-swift
default2-swift

再看

var value: String?
for _ in 1...5 {
    value = (value == nil ? "default1":"default2") + "-swift"
    print(value!)
}

输出结果
default1-swift
default2-swift
default2-swift
default2-swift
default2-swift

欢迎加入 iOS(swift)开发互助群:QQ群号:558179558, 相互讨论和学习!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。