Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Avoiding forced unwrapping in Swift Combine framework

In WWDC 2019 video 721, the basis of the main example starts like this:

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

That seems inadvisable. What happens if there's no userInfo, or it contains no "data" key, or it isn't a Data? We'll force-unwrap nil and crash. What's the best practice here?

like image 397
matt Avatar asked Mar 04 '23 19:03

matt


1 Answers

Use compactMap instead:

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

If our closure produces an Optional Data, it is unwrapped and we publish the Data. If our closure produces nil, nothing happens (nothing is published).

(It is surprising that the video doesn't write it that way. In Apple's defence, as MartinR and Itai Ferber point out, the video assumes that we ourselves are posting the notification, so we know for sure what's in the user info and force-unwrapping is reasonable. This question and answer focuses on the common situation where you've subscribed to a notification from a framework, such as Cocoa. Besides, I can't believe it's ever a bad idea to unwrap safely; in my own code, before the Combine framework, I have always unwrapped userInfo values safely even when I myself am posting the notification.)

like image 112
matt Avatar answered Mar 23 '23 02:03

matt