问题
In my app, I have this page named "TicketDetailViewController" in which i have 3 labels and an imageView in which data is displayed from previous page. Now what i want is when i click on my "sendtowatch" button, i want to send the displayed data i.e 3 labels and an imageView to my apple watch where there also i have taken 3 labels and an imageView in its storyboard. The problem is i am using FMDB database for storing and retrieving data. Now on my button click from my IOS app, the displayed data will be saved in Database and at the same time i also needs to retrieve it so that the watch can receive the latest data that i have stored in database. I have tried the solution but no luck.
here is my screenshot for my running app page below screenshot for my running app
my source code from IOS side is below:
@IBAction func sendToWatch(sender: AnyObject) {
let ticketDB = FMDatabase(path: databasePath as String)
if ticketDB.open()
{
let insertSQL = "INSERT INTO TICKET (image, ticket_category, ticket_type, date, time) VALUES ('\(display_image.image!)', '\(ticket_category.text!)', '\(ticket_type_name.text!)', '\(ticket_date.text!)', '\(ticket_time.text!)')"
let result = ticketDB.executeUpdate(insertSQL,withArgumentsInArray: nil)
if !result
{
print("Error: \(ticketDB.lastErrorMessage())")
} else
{
let alt = PMAlertController(title: "Success!", description: "Your data is saved to Database!", image: UIImage(named: ""), style: .Alert)
alt.addAction(PMAlertAction(title: "OK!", style: .Default, action:
{ (ACTION) -> Void in
let ticketInfo = NSMutableDictionary()
let ticketDB = FMDatabase(path: self.databasePath as String)
if ticketDB.open()
{
let querySQL = "SELECT * FROM TICKET"
let result: FMResultSet? = ticketDB.executeQuery(querySQL, withArgumentsInArray: nil)
if let result = result
{
self.ticketDataArray = NSMutableArray()
while result.next()
{
ticketInfo["ticket_category"] = self.ticket_category.text
ticketInfo["ticket_type"] = self.ticket_type_name.text
ticketInfo["date"] = self.ticket_date.text
ticketInfo["time"] = self.ticket_time.text
ticketInfo["image"] = self.display_image.image
print("Data: \(ticketInfo)")
}
let dict = ["Watchdat":ticketInfo]
self.session.sendMessage(dict, replyHandler: { (replayDic: [String:AnyObject]) -> Void in
print(replayDic["Watchdat"])
}, errorHandler: { (error:NSError) -> Void in
print(error.description)
})
}else
{
print("Error: \(ticketDB.lastErrorMessage())")
}
ticketDB.close()
}
}))
self.presentViewController(alt, animated: true, completion: nil)
print(databasePath)
}
}
my source code from watch side is below
class InterfaceController: WKInterfaceController, WCSessionDelegate {
var session: WCSession!
@IBOutlet var watch_displayImage: WKInterfaceImage!
@IBOutlet var watch_ticket_category: WKInterfaceLabel!
@IBOutlet var watch_ticketType: WKInterfaceLabel!
@IBOutlet var watch_ticketTime: WKInterfaceLabel!
@IBOutlet var watch_ticketDate: WKInterfaceLabel!
override func awakeWithContext(context: AnyObject?) {
super.awakeWithContext(context)
if WCSession.isSupported()
{
session = WCSession.defaultSession()
session.delegate = self
session.activateSession()
}
}
override func willActivate() {
// This method is called when watch view controller is about to be visible to user
super.willActivate()
}
func session(session: WCSession, didReceiveMessage message: [String : AnyObject], replyHandler: ([String : AnyObject]) -> Void) {
print(message.values)
var dict = Dictionary<String,AnyObject>()
watch_ticket_category.setText(dict["Watchdat"]! as? String)
}
}
回答1:
On the iOS side:
You spend the time constructing an array of tickets, but then don't do anything with that array. You passed a single ticket's dictionary, instead of passing an array of ticket dictionaries.
let ticketInfo = NSMutableDictionary()
...
self.ticketDataArray = NSMutableArray()
while result.next()
{
ticketInfo.setObject(result.stringForColumn("image"), forKey: "image")
ticketInfo.setObject(result.stringForColumn("ticket_category"), forKey: "ticket_category")
ticketInfo.setObject(result.stringForColumn("ticket_type"), forKey: "ticket_type")
ticketInfo.setObject(result.stringForColumn("date"), forKey: "date")
ticketInfo.setObject(result.stringForColumn("time"), forKey: "time")
self.ticketDataArray.addObject(ticketInfo)
}
let dict = ["Watchdat":ticketInfo]
You should either omit constructing the array, or pass the right value intended for that key.
On the watchOS side:
var dict = Dictionary<String,AnyObject>()
watch_ticket_category.setText(dict["Watchdat"]! as? String)
The dictionary you're checking is a new, empty dictionary you just created. However, the phone's data that the watch received was passed to didReceiveMessage
in the message
parameter. If you check that dictionary, you should find what you're expecting.
Note that the value for "Watchdat" key can't be conditionally cast to a String. You also need to correct that, depending on whether you meant that key's value to be a dictionary or an array.
If you meant for it to be a nested dictionary, as your code is written now, you'd have to set each label, like so:
watch_ticket_category.setText(message["Watchdat"]!["ticket_category"])
Regarding the image:
Your record's image column type is a string, but you expect to the watch to display an WKInterfaceImage
. If you intended to pass an image to the watch, you'll also need to fix that code on the iOS side.
There are plenty of answers on SO explaining how to transfer an image to the watch. The two things you should keep in mind are:
The size of the image. Don't waste time and battery life transferring a high-res image which will end up being displayed on a smaller watch screen. Scale the image before transferring it.
The max payload size that
sendMessage
supports, especially if you're intending to transfer an array of tickets (and images), instead of a single ticket.
来源:https://stackoverflow.com/questions/39072103/send-dictionary-data-to-apple-watch-from-ios-applicaton