简体   繁体   English

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

[英]Why can we chain flatMap to UserDefaults.standard.data

In an article about UserDefaults in iOS development, I saw a code snippet where flatMap is chained to UserDefaults.standard.data like below:在 iOS 开发中有关 UserDefaults 的文章中,我看到了一个代码片段,其中 flatMap 链接到 UserDefaults.standard.data,如下所示:

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

Does anyone know Why can we use.flatMap here?有谁知道为什么我们可以在这里使用.flatMap?

Because UserDefaults.standard.data(forKey:) returns Data?因为UserDefaults.standard.data(forKey:)返回Data? - an Optional<Data> , and Optional has a .flatMap method . - 一个Optional<Data> ,并且Optional有一个.flatMap方法

Specifically here, the flatMap closure gets a non-optional Data , and attempts to decode it returning another [URL:Bool]?具体来说, flatMap闭包获取一个非可选的Data ,并尝试对其进行解码,返回另一个[URL:Bool]? (also, an optional because of try? ). (另外,由于try? )。

I can guess why are you confused, although im not sure.我可以猜到你为什么感到困惑,尽管我不确定。 I think you think that .map (and it's brothers, .flatMap and .compactMap ) can only be used on Collections (eg an Array).我认为您认为.map (以及它的兄弟.flatMap.compactMap )只能用于 Collections (例如数组)。 That is completely wrong.那是完全错误的。 .map (and the other 2) have a meaning of transformation , not iterating through an collection/array. .map (和其他 2 个)具有转换的含义,而不是遍历集合/数组。 So while they can be used on arrays, they have many more use-cases as well.因此,虽然它们可以在 arrays 上使用,但它们也有更多的用例。
You can read more about differences between those 3 kinds of map here .您可以在此处阅读有关这 3 种map之间差异的更多信息。
In the code you showed, the author of that blog post has used .flatMap with intention of transforming an Optional<Data> value (aka Data?) to [URL: Bool] which is the value he wants.在您展示的代码中,该博客文章的作者使用.flatMapOptional<Data>值(又名 Data?)转换为他想要的值[URL: Bool]

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

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

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM