Transferring Dictionaries in Queues To and From the Watch - Apple Watch - iOS 9 Swift Programming Cookbook (2015)

iOS 9 Swift Programming Cookbook (2015)

Chapter 2. Apple Watch

2.4 Transferring Dictionaries in Queues To and From the Watch

Problem

You want to send dictionaries of information to and from the watch in a queuing (FIFO) fashion.

Solution

Call the transferUserInfo(_:) method on your WCSession on the sending part. On the receiving part, implement the session(_:didReceiveUserInfo:) method of the WCSessionDelegate protocol.

NOTE

A lot of the things that I’ll refer to in this recipe have been discussed already in Recipe 2.3, so have a look if you feel a bit confused.

Discussion

Create a single view app in iOS and put your root view controller in a nav controller. Then add a watch target to your app (see Figure 2-1). Make sure that your root view controller in IB looks like Figure 2-13.

Figure 2-13. Place a label and a button on your UI

Hook up the label to a variable in your code named statusLbl and hook up the button to a variable named sendBtn. Hook up your button’s action to a method in your code called send(). The top of your vc should now look like:

import UIKit

import WatchConnectivity

class ViewController: UIViewController, WCSessionDelegate {

@IBOutlet var statusLbl: UILabel!

@IBOutlet var sendBtn: UIButton!

...

You also need a property that can set the status for you on your label. The property must be on the main thread, because WCSession methods (where we may want to set our status property) usually are not called on the main thread:

var status: String?{

get{return self.statusLbl.text}

set{

dispatch_async(dispatch_get_main_queue()){

self.statusLbl.text = newValue

}

}

}

When the user presses the send button, we will use the WCSession.defaultSession().transferUserInfo(_:) method to send a simple dictionary whose only key is kCFBundleIdentifierKey and a value that will be our Info.plist’s bundle identifier:

@IBAction func send() {

guard let infoPlist = NSBundle.mainBundle().infoDictionary else{

status = "Could not get the Info.plist"

return

}

let key = kCFBundleIdentifierKey as String

let plist = [

key : infoPlist[key] as! String

]

let transfer = WCSession.defaultSession().transferUserInfo(plist)

status = transfer.transferring ? "Sent" : "Could not send yet"

}

The transferUserInfo(_:) method returns an object of type WCSessionUserInfoTransfer that has properties such as userInfo and transferring and a method called cancel(). You can always use the cancel() method of an instance of WCSessionUserInfoTransfer to cancel the transfer of this item if it is not already transferring. You can also find all the user info transfers that are ongoing by using the outstandingUserInfoTransfers property of your session object.

NOTE

The app also contains code to disable the button if the watch app is not reachable, but I won’t discuss that code here because we have already discussed it in Recipe 2.3 and Recipe 2.2.

On the watch side, in InterfaceController, write the exact same code that you wrote in Recipe 2.3. In the ExtensionDelegate class, however, our code will be a bit different. Its status property is exactly how we wrote it in Recipe 2.3.

When the applicationDidFinishLaunching() method of our delegate is called, we set up the session just as we did in Recipe 2.2. We will wait for the session(_:didReceiveUserInfo:) method of the WCSessionDelegate protocol to be called. There, we will simply read the bundle identifier from the user info and display it in our view controller:

func session(session: WCSession,

didReceiveUserInfo userInfo: [String : AnyObject]) {

guard let bundleVersion = userInfo[kCFBundleIdentifierKey as String]

as? String else{

status = "Could not read the bundle version"

return

}

status = bundleVersion

}

If you run the iOS app, your UI should look like Figure 2-14.

Figure 2-14. Our app has detected that the watch app is reachable so the button is enabled

And your watch app should look like Figure 2-15.

Figure 2-15. The watch app is waiting for incoming user info data

When you press the send button, the user interface will change to Figure 2-16.

Figure 2-16. The data is sent to the watch

And the watch app will look like Figure 2-17.

Figure 2-17. The watch app successfully received our user info

See Also