I tried passing a dictionary with an enum
as key in a Notification
([TestEnum: String]
). Unfortunately, type-casting the dictionary to [TestEnum: String]
fails after receiving the notification.
enum TestEnum {
case test
}
class NotificationTest {
var sender: String = "" {
didSet {
NotificationCenter.default.post(name: Notification.Name(rawValue: "Test"), object: nil, userInfo: [TestEnum.test: "test"])
}
}
init() {
NotificationCenter.default.addObserver(self, selector: #selector(notificationReceived(_:)), name: Notification.Name(rawValue: "Test"), object: nil)
}
@objc func notificationReceived(_ notification: Notification) {
print("Notification Received")
guard let userInfo = notification.userInfo as? [TestEnum: String] else { return } // Type casting fails here even though userInfo shows a TestEnum key in debugger
print(userInfo[.test])
}
}
let test = NotificationTest()
test.sender = "blah"
However, if i use rawValue
of TestEnum
as key, it works fine when notification.userInfo
is casted to [String: String]
.
Just had a look at the source code of AnyHashable
, when you cast a Hashable
(your enum) to AnyHashable
, it is wrapped in the property base
within AnyHashable
. Therefore, it cannot be directly cast back to your enum. Here uses reduce
to transform [AnyHashable:Any]
to [TestEnum:String]
:
@objc func notificationReceived(_ notification: Notification) {
print("Notification Received")
guard let userInfo = notification.userInfo?.reduce(into: [TestEnum:String](), { (result, entry) in
if let key = entry.key.base as? TestEnum
{
result[key] = entry.value as? String
}
}) else {
print(notification.userInfo)
return
} // Type casting fails here even though userInfo shows a TestEnum key in debugger
print(userInfo[.test])
}
And because AnyHashable
conforms to CustomStringConvertible
, it can be cast to String
directly.