在 guard let url 之后,值仍然需要解包

After guard let url the value still needs to be unwrapped

a singleton class 中,我正在尝试使用以下代码将 3 个 URL 存储在字典中:

class DownloadManager {
    static let instance = DownloadManager()
    
    let urls = [
        "en" : URL(string: "https://wordsbyfarber.com/ws/top"),
        "de" : URL(string: "https://wortefarbers.de/ws/top"),
        "ru" : URL(string: "https://slova.de/ws/top")
    ]
    
    var cancellables = Set<AnyCancellable>()

    private init() {
        getTops()
    }
    
    func getTops() {
        guard let url = urls["en"] else { return }
        
        URLSession.shared.dataTaskPublisher(for: url) // COMPILE ERROR
            .tryMap(handleOutput)
            .decode(type: TopResponse.self, decoder: JSONDecoder())
            .sink { completion in
                print(completion)
            } receiveValue: { fetchedTops in
                // ... store entities in Core Data
            }
            .store(in: &cancellables)
    }

但由于某些原因,行 guard let url = urls["en"] else { return } 不足以展开值:

发生这种情况是因为 URL 构造函数可能 return 为零吗?

或者因为字典可能没有键值?

为什么这里的 guard 语句不够用?

urls 实际上是 [String: URL?] 类型。请注意,值类型是可选的,因为 URL.init(string:) 是可失败的。

当您尝试从此字典中获取值时,您会得到 URL??guard 只展开可选层的一层。

解包嵌套可选(无论多少层)的一种方法是使用 as?:

guard let url = urls["en"] as? URL else { return }

Is this happening because the URL constructor might return nil?

是的。

let urls = [
    "en" : URL(string: "https://wordsbyfarber.com/ws/top"),
    "de" : URL(string: "https://wortefarbers.de/ws/top"),
    "ru" : URL(string: "https://slova.de/ws/top")
]

创建一个带有可选 URL 的字典 ([String: URL?]),您的解包仅与字典的内容有关。

使用

let urls = [
    "en" : URL(string: "https://wordsbyfarber.com/ws/top")!,
    "de" : URL(string: "https://wortefarbers.de/ws/top")!,
    "ru" : URL(string: "https://slova.de/ws/top")!
]

对于像这样的硬编码 URL,或者如果不清楚 URL 是否有效则双重解包。

那是 Url 初始值设定项 returns 一个可选的 + Dictionary 的可选包装,如果您确定所有网址都有效,那么

 guard let url = urls["en"] else { return } 
 URLSession.shared.dataTaskPublisher(for: url!) // add only !

或仅

 URLSession.shared.dataTaskPublisher(for: urls["en"]!!)   // add !!