swift 可选值简介3

130 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第18天,点击查看活动详情

在字符串插值中使用可选值

我们在打印可选值时候会编译器会发出警告,主要是为了防止把Optional(...)或nil显示到文本,需要对其进行解包,但是所有类型是允许插入到字符串中的包括Optional类型,所以编译器发出的是警告

let bodyTemperature: Double? = 37.0
let bloodGlucose: Double? = nil
print(bodyTemperature) // Optional(37.0)
// 警告:表达式被隐式强制从 'Double?' 转换为 Any
print("Blood glucose level: (bloodGlucose)") // Blood glucose level: nil
// 警告:字符串插值将使用调试时的可选值描述,
// 请确认这确实是你想要做的。

如果想去除警告可以有以下几种做法

  • 使用as Any 进行转换
  • 确定不为nil,用!强制解包
  • String(describing:...)包装
  • nil合并运算符提供默认值(a ?? "c")

最后一种做法的不足在于 ?? 俩侧的类型必须匹配,如果左侧为Double?类型,默认值也是Double类型,如果一开始能提供字符串类型就比较方便,我们可以自定义运算符进行处理

infix operator ???: NilCoalescingPrecedence

public func ???<T>(optional: T?, defaultValue:@autoclosure ()-> String) -> String {
    switch optional {
    case let value?: return String(describing: value)
    case nil: return defaultValue()
    }
}

@autoclosure表示只要在需要的时候才会对第二个表达式进行求值

let bodyTemperature: Double? = 37.0
let bloodGlucose: Double? = nil
print("Body temperature: (bodyTemperature ??? "n/a")")
print("Blood glucose level: (bloodGlucose ??? "n/a")")

Body temperature: 37.0
Blood glucose level: n/a
map

一种实现方式

extension Optional {
    func map<U>(transform: (Wrapped)->U) -> U? {
        guard let value = self else { return nil }
        return transform(value)
    }
}
let firstChar = characters.first.map { String($0) }

这里map只操作一个值,可选值为nil时候也会返回nil

当你想为数组提供一个变种的reduce方法,不接受初始值,由于Swift有重载,所以可以直接命名为reduce

extension Array {
    func reduce(_ nextPartialResult:(Element, Element) -> Element) -> Element? {
        guard let fst = first else { return nil }
        return dropFirst().reduce(fst, nextPartialResult)
    }
}
[1, 2, 3].reduce(+)

这里可以用map代替guard

func alt_reduce(_ nextPartialResult:(Element, Element) -> Element) -> Element? {
        return first.map { return reduce($0, nextPartialResult) }
 }
compactMap

一种实现方式

extension Sequence {
    func alt_commpactMap<T>(_ transform: (Element) -> T?) -> [T] {
        return lazy.map(transform).filter { $0 != nil }.map { $0! }
    }
}
  • lazy将数组的创建放在最后一刻,在处理较大的序列时候还是不错的,避免多个作为中间结果的数组的内存分配。实际**compactMap*不是这么做的