I currently have messaging between an iOS app and WatchOS app happening. I am using a hardcoded string of message for the key. This works, but I want to have several types of messages. So I made an enum with type of String.
enum DeviceMessage: String {
case Foo, Bar
}
In a view I want to call the WCSession send a message using my own method:
func sendMessage(msg:[String : Any]){
if self.session.isReachable == false {
self.session.transferUserInfo(msg)
} else {
self.session.sendMessage(msg, replyHandler: nil){ error in
print(error.localizedDescription)
}
}
}
Instead of String for the dictionary key, I want to be able to use .Foo
. Without using RawValue
, etc. What is the best way to set this up? In this vein, I would also like to set my delegate method for incoming messages to use DeviceMessage as a key too so I can evaluate it without using hardcoded strings for the keys.
func session(_ session: WCSession, didReceiveUserInfo userInfo: [String : Any] = [:]) {
print(message)
DispatchQueue.main.async {
self.message = userInfo["message"] as? String ?? "Unknown"
}
}
CodePudding user response:
I added this to the file where my enum lives:
func DeviceMessageRawKey(key: DeviceMessage) -> String { return key.rawValue }
So now I can send and receive using String (no changes) but when being specific, I can use the enum.
func session(_ session: WCSession, didReceiveMessage message: [String : Any]) {
DispatchQueue.main.async {
if let val = message[DeviceMessageRawKey(key: .Foo)] {
self.message = val as? String ?? "Unknown"
}
}
}
...
self.model.sendMessage(msg: [DeviceMessageRawKey(key: .Foo) : "Need data."])
CodePudding user response:
The only thing required for something to be a dictionary key is that it implements the Hashable
protocol. Since your enum has a raw value of type String
, you can just have it conform to the protocol and not implement anything.
enum DeviceMessage: String, Hashable {
case Foo, Bar
}
You can then do:
let dict: [DeviceMessage: Any] = [.Foo: "hello"]
You will still need to convert from [String: Any]
-> [DeviceManager: Any]
(and vice versa) somewhere, but at least you can work with just [DeviceManager: Any]
outside of the class that sends/receives messages.