Core Bluetooth in watchOS Tutorial

Learn how to communicate with external BLE devices from within watchOS in this Core Bluetooth tutorial! By Audrey Tam.

Leave a rating/review
Save for later
Share
You are currently viewing page 3 of 3 of this article. Click here to view the first page.

Reduce the Amount of Text to Send

Data transfer to the Watch is slower than to an iOS device, so open the iOS app’s Main.storyboard, and delete the second sentence from PeripheralViewController‘s textView, leaving only Lorem ipsum dolor sit er elit lamet sample text.

Copy-Pasting and Editing CentralViewController code

First, select SharedConstants.swift, and open the file inspector to add BT_WatchKit_App Extension to its target membership:

Now you’ll mostly copy code from CentralViewController.swift, paste it into InterfaceController.swift, and do a small amount of editing.

First, import CoreBluetooth:

import CoreBluetooth

Below the outlets, copy and paste the central manager, peripheral, characteristic and data properties, then edit mapCharacteristic to set the title of mapButton, and add a similar observer to textCharacteristic:

var centralManager: CBCentralManager!
var discoveredPeripheral: CBPeripheral?
var textCharacteristic: CBCharacteristic? {
  didSet {
    if let _ = self.textCharacteristic {
      textButton.setTitle("Text Me")
    }
  }
}
var data = Data()
var mapCharacteristic: CBCharacteristic? {
  didSet {
    if let _ = self.mapCharacteristic {
      mapButton.setTitle("Map Me")
    }
  }
}

This lets the user know that the Watch app has discovered the text and map characteristics, so it’s now safe to read or write them.

Copy and paste the helper methods scan() and cleanup(), then copy and paste the two delegate extensions. Change the two occurrences of extension CentralViewController to extension InterfaceController:

// MARK: - Central Manager delegate
extension InterfaceController: CBCentralManagerDelegate {

and

// MARK: - Peripheral Delegate
extension InterfaceController: CBPeripheralDelegate {

In peripheral(_:didDiscoverCharacteristicsFor:error:), delete the line that subscribes to textCharacteristic:

peripheral.setNotifyValue(true, for: characteristic)

Subscribing causes the peripheral to send the text data, so you’ll move this to the Text Me button’s action, giving the user more control over how the Watch app spends its restricted BLE allowance.

In peripheral(_:didUpdateValueFor:error:), replace the textView.text line (where the error is) with these two lines:

statusLabel.setHidden(true)
textLabel.setText(String(data: data, encoding: .utf8))

And add this line just below the line that creates stringFromData:

statusLabel.setText("received \(stringFromData ?? "nothing")")

Everything happens more slowly on the Watch, so you’ll use statusLabel to tell the user what’s happening while they wait. Just before the transferred text appears, you hide statusLabel, to make room for the text.

Use statusLabel in other places: add this line to scan():

statusLabel.setText("scanning")

And this line to centralManager(_:didDiscover:advertisementData:rssi:):

statusLabel.setText("discovered peripheral")

And to centralManager(_:didConnect:):

statusLabel.setText("connected to peripheral")

Add similar log statements to peripheral delegate methods, when services and characteristics are discovered.

Next, scroll up to awake(withContext:), and copy-paste this line from viewDidLoad():

centralManager = CBCentralManager(delegate: self, queue: nil)

Delete the methods willActivate() and didDeactivate().

Now fill in the actions. Add these lines to textMe():

guard let characteristic = textCharacteristic else { return }
discoveredPeripheral?.setNotifyValue(true, for: characteristic)

Tapping the Text Me button subscribes to textCharacteristic, which triggers peripheralManager(_:central:didSubscribeTo:) to send data.

Next, copy these lines from mapUserLocation() into mapMe():

guard let characteristic = mapCharacteristic else { return }
discoveredPeripheral?.writeValue(Data(bytes: [1]), for: characteristic, type: .withoutResponse)

mapUserLocation() and mapMe() do the same thing: write the value of mapCharacteristic, which triggers peripheralManager(_:didReceiveWrite:) to open the Maps app.

Before you implement resetCentral(), add this helper method:

fileprivate func resetUI() {
  statusLabel.setText("")
  statusLabel.setHidden(false)
  textLabel.setText("Transferred text appears here")
  textButton.setTitle("wait")
  mapButton.setTitle("wait")
}

You’re just setting the label and button titles back to what they were, and unhiding statusLabel.

Now add these two lines to resetCentral():

cleanup()
resetUI()

Build and run on your Apple Watch + iPhone. You’ll probably have to do this a couple of times, to “trust this developer” on the iPhone and on the Watch. At the time of writing, instead of telling you what to do, the Watch displays this error message:

Press the digital crown to manually open the app on your Watch, and trust this developer. The app will then start, but stop it, then build and run again. Select Peripheral mode on the iPhone, and turn on Advertising.

And wait. Scanning, connection and discovery take longer when the central is a Watch instead of an iPhone. When the Watch app discovers the TextOrMap characteristics, it updates the button titles:

Tap Text Me, and wait. You’ll see the text appear on the Watch, and statusLabel disappears:

Tap Map Me, and allow use of your location. Tap Map Me again, and the iPhone opens the Maps app at your location.

Stop the Watch app in Xcode, and close the iPhone app.

Congratulations! You’ve built a Watch app that uses an iPhone as a Bluetooth LE peripheral! Now you can connect all the things!

Where to Go From Here?

You can download the completed project for the tutorial here.

The audio recording and playback API of watchOS 4 makes it possible to deliver a smooth multimedia experience on the Apple Watch even when the paired iPhone isn’t in proximity. This is a technology with endless possibilities.

If you enjoyed what you learned in this tutorial, why not check out the complete watchOS by Tutorials book, available in our store?

Here’s a taste of what’s in the book:

Chapter 1, Hello, Apple Watch!: Dive straight in and build your first watchOS 4 app — a very modern twist on the age-old “Hello, world!” app.

Chapter 2, Designing Great Watch Apps: Talks about the best practices based on Apple recommendations in WWDC this year, and how to design a Watch app that meets these criteria.

Chapter 3, Architecture: watchOS 4 might support native apps, but they still have an unusual architecture. This chapter will teach you everything you need to know about this unique aspect of watch apps.

Chapter 4, UI Controls: There’s not a `UIView` to be found! In this chapter you’ll dig into the suite of interface objects that ship with WatchKit–watchOS’ user interface framework.

Chapter 5, Pickers: `WKInterfacePicker` is one of the programmatic ways to work with the Digital Crown. You’ll learn how to set one up, what the different visual modes are, and how to respond to the user interacting with the Digital Crown via the picker.

Chapter 6, Layout: Auto Layout? Nope. Springs and Struts then? Nope. Guess again. Get an overview of the layout system you’ll use to build the interfaces for your watchOS apps.

Chapter 7, Tables: Tables are the staple ingredient of almost any watchOS app. Learn how to set them up, how to populate them with data, and just how much they differ from `UITableView`.

Chapter 8, Navigation: You’ll learn about the different modes of navigation available on watchOS, as well as how to combine them.

Chapter 9, Digital Crown and Gesture Recognizers: You’ll learn about accessing Digital Crown raw data, and adding various gesture recognizers to your watchOS app interface.

Chapter 10, Snapshot API: Glances are out, and the Dock is in! You’ll learn about the Snapshot API to make sure that the content displayed is always up-to-date.

Chapter 11, Networking: `NSURLSession`, meet Apple Watch. That’s right, you can now make network calls directly from the watch, and this chapter will show you the ins and outs of doing just that.

Chapter 12, Animation: The way you animate your interfaces has changed with watchOS 3, with the introduction of a single, `UIView`-like animation method. You’ll learn everything you need to know about both animated image sequences and the new API in this chapter.

Chapter 13, CloudKit: You’ll learn how to keep the watch and phone data in sync even when the phone isn’t around, as long as user is on a known WiFi network.

Chapter 14, Notifications: watchOS offers support for several different types of notifications, and allows you to customize them to the individual needs of your watch app. In this chapter, you’ll get the complete overview.

Chapter 15, Complications: Complications are small elements that appear on the user’s selected watch face and provide quick access to frequently used data from within your app. This chapter will walk you through the process of setting up your first complication, along with introducing each of the complication families and their corresponding layout templates.

Chapter 16, Watch Connectivity: With the introduction of native apps, the way the watch app and companion iOS app share data has fundamentally changed. Out are App Groups, and in is the Watch Connectivity framework. In this chapter you’ll learn the basics of setting up device-to-device communication between the Apple Watch and the paired iPhone.

Chapter 17, Audio Recording: As a developer, you can now record audio directly on the Apple Watch inline in your apps, without relying on the old-style system form sheets. In this chapter, you’ll gain a solid understanding of how to implement this, as well as learn about some of the idiosyncrasies of the APIs, which are related to the unique architecture of a watch app.

Chapter 18, Interactive Animations with SpriteKit and SceneKit: You’ll learn how to apply SpriteKit and SceneKit in your Watch apps, and how to create interactive animations of your own.

Chapter 19, Advanced Watch Connectivity: In Chapter 15, you learned how to set up a Watch Connectivity session and update the application context. In this chapter, you’ll take a look at some of the other features of the framework, such as background transfers and real-time messaging.

Chapter 20, Advanced Complications: Now that you know how to create a basic complication, this chapter will walk you through adding Time Travel support, as well giving you the lowdown on how to efficiently update the data presented by your complication.

Chapter 21, Handoff Video Playback: Want to allow your watch app users to begin a task on their watch and then continue it on their iPhone? Sure you do, and this chapter will show exactly how to do that through the use of Handoff.

Chapter 22, Core Motion: The Apple Watch doesn’t have every sensor the iPhone does, but you can access what is available via the Core Motion framework. In this chapter, you’ll learn how to set up Core Motion, how to request authorization, and how to use the framework to track the user’s steps.

Chapter 23, HealthKit: The HealthKit framework allows you to access much of the data stored in user’s health store, including their heart rate! This chapter will walk you through incorporating HealthKit into your watch app, from managing authorization to recording a workout session.

Chapter 24, Core Location: A lot of apps are now location aware, but in order to provide this functionality you need access to the user’s location. Developers now have exactly that via the Core Location framework. Learn everything you need to know about using the framework on the watch in this chapter.

Chapter 25, Core Bluetooth: In watchOS 4, you can pair and interact with BLE devices directly. Learn how to send control instructions and other data directly over Bluetooth.

Chapter 26, Localization: Learn how to expand your reach and grow a truly international audience by localizing your watch app using the tools and APIs provided by Apple.

Chapter 27, Accessibility: You want as many people as possible to enjoy your watch app, right? Learn all about the assistive technologies available in watchOS, such as VoiceOver and Dynamic Type, so you can make your app just as enjoyable for those with disabilities as it is for those without.

One thing you can count on: after reading this book you’ll have all the experience necessary to build rich and engaging apps for the Apple Watch platform.

And to help sweeten the deal, the digital edition of the book is on sale for $49.99! But don’t wait — this sale price is only available for a limited time.

Speaking of sweet deals, be sure to check out the great prizes we’re giving away this year with the iOS 11 Launch Party, including over $9,000 in giveaways!

To enter, simply retweet this post using the #ios11launchparty hashtag by using the button below:


We hope you enjoy this update, and stay tuned for more book releases and updates!