避免在 Swift Combine 框架中强制解包
Avoiding forced unwrapping in Swift Combine framework
在WWDC 2019视频721中,主要示例的基础是这样开始的:
let trickNamePublisher = NotificationCenter.default.publisher(for: .newTrickDownloaded)
.map { notification in
return notification.userInfo?["data"] as! Data
}
这似乎不可取。如果没有 userInfo
,或者它不包含 "data"
键,或者它不是数据,会发生什么情况?我们将强制展开 nil
并崩溃。这里的最佳做法是什么?
改用compactMap
:
let trickNamePublisher = NotificationCenter.default.publisher(for: .newTrickDownloaded)
.compactMap { [=10=].userInfo?["data"] as? Data }
如果我们的闭包产生一个可选数据,它会被解包并发布数据。如果我们的闭包生成 nil
,什么也不会发生(什么都不会发布)。
(令人惊讶的是视频没有那样写。在 Apple 的辩护中,正如 MartinR 和 Itai Ferber 指出的那样,视频假设我们自己发布了通知,所以我们确切地知道里面有什么用户信息和 force-unwrapping 是合理的。这个问题和答案集中在你从框架订阅通知的常见情况,例如 Cocoa。此外,我不敢相信它是 曾经 安全解包是个坏主意;在我自己的代码中,在 Combine 框架之前,我总是安全地解包 userInfo
值,即使我自己发布通知也是如此。)
在WWDC 2019视频721中,主要示例的基础是这样开始的:
let trickNamePublisher = NotificationCenter.default.publisher(for: .newTrickDownloaded)
.map { notification in
return notification.userInfo?["data"] as! Data
}
这似乎不可取。如果没有 userInfo
,或者它不包含 "data"
键,或者它不是数据,会发生什么情况?我们将强制展开 nil
并崩溃。这里的最佳做法是什么?
改用compactMap
:
let trickNamePublisher = NotificationCenter.default.publisher(for: .newTrickDownloaded)
.compactMap { [=10=].userInfo?["data"] as? Data }
如果我们的闭包产生一个可选数据,它会被解包并发布数据。如果我们的闭包生成 nil
,什么也不会发生(什么都不会发布)。
(令人惊讶的是视频没有那样写。在 Apple 的辩护中,正如 MartinR 和 Itai Ferber 指出的那样,视频假设我们自己发布了通知,所以我们确切地知道里面有什么用户信息和 force-unwrapping 是合理的。这个问题和答案集中在你从框架订阅通知的常见情况,例如 Cocoa。此外,我不敢相信它是 曾经 安全解包是个坏主意;在我自己的代码中,在 Combine 框架之前,我总是安全地解包 userInfo
值,即使我自己发布通知也是如此。)