【问题标题】:Avoiding forced unwrapping in Swift Combine framework避免在 Swift Combine 框架中强制展开
【发布时间】:2019-06-22 16:54:27
【问题描述】:

在 WWDC 2019 视频 721 中,主要示例的基础是这样开始的:

let trickNamePublisher = NotificationCenter.default.publisher(for: .newTrickDownloaded)
    .map { notification in
        return notification.userInfo?["data"] as! Data
    }

这似乎是不可取的。如果没有userInfo,或者它不包含"data" 键,或者它不是数据,会发生什么?我们将强制解开nil 并崩溃。这里的最佳做法是什么?

【问题讨论】:

  • 在这个特定示例中,发布通知的是 your 代码,因此您知道用户数据中的内容。崩溃会显示编程错误。
  • 我正要说同样的话,但马丁抢了我。该示例显示了来自应用程序不同部分的通知;数据存在于其中的事实是不变量。如果不是这种情况,则首选compactMap
  • @ItaiFerber 关键是视频可能已经提到了这一点。此外,使用compactMap 和安全解包怎么会永远受到伤害?因此是问题中的“最佳实践”。
  • @MartinR 我会将这一区别添加到答案的表述中。
  • @matt 它当然不会受到伤害,永远 - 我认为对于这个特定的例子,更多的人熟悉map 而不是compactMap,并且能够掩盖@987654329 的事实@ 能够从流中删除值(它开始提出比这里回答的问题更多的问题)使示例保持简洁。我同意你在这里应该使用compactMap

标签: swift optional ios13 combine


【解决方案1】:

改用compactMap

let trickNamePublisher = NotificationCenter.default.publisher(for: .newTrickDownloaded)
    .compactMap { $0.userInfo?["data"] as? Data }

如果我们的闭包产生一个可选数据,它会被解包并且我们发布数据。如果我们的闭包产生nil,则什么都不会发生(什么都不会发布)。

(令人惊讶的是,视频没有这样写。在苹果的辩护中,正如 MartinR 和 Itai Ferber 指出的那样,视频假设我们自己正在发布通知,所以我们可以肯定地知道用户的内容info 和 force-unwrapping 是合理的。这个问题和答案侧重于您从框架(例如 Cocoa)订阅通知的常见情况。此外,我不敢相信它是 ever安全解包的坏主意;在我自己的代码中,在组合框架之前,我总是安全地解包 userInfo 值,即使我自己发布通知也是如此。)

【讨论】:

  • 展开基本上是:.compactMap { $0 }
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多