为什么我们可以将 flatMap 链接到 UserDefaults.standard.data

Why can we chain flatMap to UserDefaults.standard.data

在一篇关于 iOS 开发中的 UserDefaults 的文章中,我看到了一个代码片段,其中 flatMap 被链接到 UserDefaults.standard.data,如下所示:

self.isReadStatuses = UserDefaults.standard.data(forKey: "isReadStatuses")
      .flatMap { try? JSONDecoder().decode([URL: Bool].self, from: [=11=]) } ?? [:]

有谁知道为什么我们可以在这里使用.flatMap?

因为 UserDefaults.standard.data(forKey:) returns Data? - 一个 Optional<Data>,并且 Optional has a .flatMap method.

特别是这里,flatMap 闭包得到一个非可选的 Data,并尝试解码它返回另一个 [URL:Bool]?(也是可选的,因为 try? ).

我能猜到你为什么感到困惑,虽然我不确定。我想你认为 .map(和它的兄弟,.flatMap.compactMap)只能用于集合(例如数组)。那是完全错误的。 .map(和其他 2 个)具有 转换 的含义,而不是迭代 collection/array。因此,虽然它们可以用于数组,但它们也有更多的用例。
您可以阅读更多关于这 3 种 map here.
之间差异的信息 在您展示的代码中,该博客 post 的作者使用 .flatMap 的目的是 转换 一个 Optional<Data> 值(又名数据?)到[URL: Bool]这就是他想要的值。

let udData = UserDefaults.standard.data(forKey: "isReadStatuses")

// Short way:
let isReadStatuses1 = udData.flatMap {
    try? JSONDecoder().decode([URL: Bool].self, from: [=10=])
} ?? [:]

// Long way:
let isReadStatuses2: [URL: Bool]
if let data = udData {
    isReadStatuses2 = (try? JSONDecoder().decode([URL: Bool].self, from: data)) ?? [:]
} else {
    isReadStatuses2 = [:]
}