简体   繁体   中英

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:

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?

Because UserDefaults.standard.data(forKey:) returns Data? - an Optional<Data> , and Optional has a .flatMap method .

Specifically here, the flatMap closure gets a non-optional Data , and attempts to decode it returning another [URL:Bool]? (also, an optional because of 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). That is completely wrong. .map (and the other 2) have a meaning of transformation , not iterating through an collection/array. So while they can be used on arrays, they have many more use-cases as well.
You can read more about differences between those 3 kinds of map here .
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.

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 = [:]
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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