Search code examples
iosswiftwatchkitwatchos

watchOS can't sendMessage() a struct


I have this struct declared in both my iOS app and its Apple Watch extension

struct nonIndexStruct {
    let name: [String]
    let message: [String]
}

I create an object like this

let nIS = nonIndexStruct(name: sortedNameArray.map({ ($0 ).name }), message: sortedNameArray.map({ ($0 ).name }))

In order to pass it to my Apple Watch Extension, I put the object into a dict

let chatsMasterDict:[String: Any] = ["chatsMaster": nIS]

Printing this works perfectly fine, all the data is available in this object. To send it, I call

session.sendMessage(chatsMasterDict, replyHandler: nil, errorHandler: nil)

Now the problem is that nothing arrives on the Apple Watch side. The errorHandler only prints something when the Apple Watch App is not opened. (about the watch app not being open)

The receiving method on the Apple Watch looks like this and it prints everything it receives - except for the case shown above, the method simply doesn't get called.

func session(_ session: WCSession, didReceiveMessage message: [String : Any]) {
    print("didReceive")
    print (message)

    if let val = message["chatsMaster"]{
        print("chatsMaster came")
    . . .

My best guess is that although the struct is available to both systems, the bridge in between doesn't "know of" it and can't handle it. When closing the app, I also get

Could not cast value of type '__NSCFString' (0x12e9fe0) to 'NSArray' (0x12ea670). 2017-09-06 12:23:24.237016+0200 APPNAME WatchKit Extension[20802:3718623] Could not cast value of type '__NSCFString' (0x12e9fe0) to 'NSArray' (0x12ea670).

But again, this only happens when I stop the process so idk whether that relates to my problem.

EDIT: Apple Watch documentation says

The keys and values of your dictionary must all be property list types, because the data must be serialized and sent wirelessly.

so that's probably why it's not working. What's the best workaround? Making it Data would be a bit overkill I guess as the contents of my struct are pretty simple :/


Solution

  • It is really weird that you are not getting an error, but the core of the problem is that you are trying to send a custom struct using the sendMessage function, which can only be used to send property list types.

    The best solution is (since your struct is really simple and all of its properties are property list types) probably to convert your struct to a dictionary and send the dictionary using sendMessage.

    struct nonIndexStruct {
        let name: [String]
        let message: [String]
    
        func toDictionary()->[String:[String]]{
            var dict = [String:[String]]()
            dict["name"] = self.name
            dict["message"] = self.message
            return dict
        }
    }
    
    let chatsMasterDict = ["chatsMaster": nIS.toDictionary()]
    session.sendMessage(chatsMasterDict, replyHandler: nil, errorHandler: nil)