-1

I am using WatchConnectivity to send an array of string values from the iPhone to the Watch, but when doing so I get the following error.

Could not cast value of type '__NSCFArray' (0x591244) to 'NSString' (0x9f7458).

I have been having some slight trouble sending an array of strings within a dictionary to the watch and then saving the array to use in a WKInterfaceTable.

Does anybody know where I am going wrong and how I can display the array on the watch ?

iPhone

After receiving the first message from the watch to send the data the iPhones didRecieveMessage does the following.

There is an array called objectsArray and each object has a string property called title. I create a new array for all the title values and use the array in a dictionary to send to the watch.

func session(session: WCSession, didReceiveMessage message: [String : AnyObject], replyHandler: ([String : AnyObject]) -> Void) {

  var watchArray = [""]

  for object in self.objectsArray {
     watchArray.append(object.title)
  }

  print("Received message from watch and sent array. \(watchArray)")
  //send a reply
  replyHandler( [ "Value" : [watchArray] ] )

}

Watch

var objectTitlesArray = ["String"]


//Display Array in WKInterfaceTable

func loadTableData() {
    table.setNumberOfRows(self.tasks.count, withRowType: "CellRow")
    if self.tasks.count > 0 {
        for (index, objectTitle) in self.objectTitlesArray.enumerate() {
            let row = self.table.rowControllerAtIndex(index) as! CellRowController
            row.tableCellLabel.setText(objectTitle)
        }
     }
}  


//Saving the Array

func session(session: WCSession, didReceiveMessage message: [String : AnyObject], replyHandler: ([String : AnyObject]) -> Void) {

    let value = message["Value"] as! [String]

    dispatch_async(dispatch_get_main_queue()) {
        self.objectTitlesArray = value
        print("Received Array and refresh table")
        loadTableData()
    }

    //send a reply
    replyHandler(["Value":"Yes"])

}  

UPDATE

The error mentioned seems to have something to do with the refresh action when setting label text to value. However after commenting the lines out, the array still seems to not be displaying in the WKInterfaceTable and none of the print statements are outputted to the console.

RileyDev
  • 2,950
  • 3
  • 26
  • 61

2 Answers2

0

This is where the error occurs:

let value = message["Value"] as! [String]

In the above, you're getting the Value property in the message dictionary and explicitly casting is as a String. It should be as follows:

if let value = message["Value"] {

    dispatch_async(dispatch_get_main_queue()) {
        self.objectTitlesArray = value as! [String]
    }
}

As an aside, it looks like you're also wrapping the array of strings in another, redundant array:

replyHandler( [ "Value" : [watchArray] ] )

If you just want to send the array of strings, then the following should suffice:

replyHandler( [ "Value" : watchArray ] )

Vinny Coyne
  • 2,365
  • 15
  • 24
  • When changing casting the value of value to `[Array]` I get the following error ` Ambiguous reference to member 'Subscript' ` when I leave it as `[String]` and just edit the reply handler on the phone then I still get the same error mentioned in my question. – RileyDev Mar 16 '16 at 13:50
  • Unfortunately still get `Ambiguous reference to member 'Subscript'` :( – RileyDev Mar 16 '16 at 14:10
  • What about using `[AnyObject]` instead of `[Array]`? – JAL Mar 16 '16 at 14:22
  • I was so sure it should work now, your changes make sense. But unfortunately still get the error `Could not cast value of type '__NSCFArray' (0x520244) to 'NSString' (0x986458).` – RileyDev Mar 16 '16 at 14:49
  • Did you change the replyhandler to replyHandler( [ "Value" : watchArray ] ) ? – Vinny Coyne Mar 16 '16 at 14:53
  • It sounds like the error is happening elsewhere in your code then. Are you sure that error relates to the code you've posted? – Vinny Coyne Mar 16 '16 at 15:06
  • @VinnyCoyne My apologies, I have updated the question. – RileyDev Mar 16 '16 at 15:50
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/106490/discussion-between-vinny-coyne-and-jksdev). – Vinny Coyne Mar 16 '16 at 15:52
  • @VinnyCoyne Please check my answer. I have solved the issue. – RileyDev Mar 17 '16 at 13:36
0

The sendMessage method should handle the reply from the phone. And their is no reason to use a didRecieveMessage method on the watch if the iPhone does not use a sendMessage method.

@IBAction func fetchData() {

    let messageToSend = ["Value":"Hello iPhone"]
    session.sendMessage(messageToSend, replyHandler: { replyMessage in

        if let value = replyMessage["Value"] {
                self.objectTitlesArray = value as! [String]
                self.loadTableData()
        }

        }, errorHandler: {error in
            // catch any errors here
            print(error)
    })

}
RileyDev
  • 2,950
  • 3
  • 26
  • 61