一起养成写作习惯!这是我参与「掘金日新计划 · 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*不是这么做的