# Bluetooth Device Pairing UI in SwiftUI (Free Template)

> By Lawrence Arya, Founder & CEO of VP0. Published 2026-05-31, updated 2026-06-02. 4 min read.
> Source: https://vp0.com/blogs/bluetooth-device-pairing-ui-swiftui

A pairing screen is a state machine you can see: scanning, found, connecting, connected, failed. Get the states right and it feels trustworthy.

**TL;DR.** A Bluetooth Low Energy pairing screen scans for nearby devices, shows them in a live list, lets the user pick one, and walks through connecting with explicit states: scanning, found, connecting, connected, and failed. You build the UI from a free VP0 design and drive it with Core Bluetooth and CBCentralManager. The honest scope: you own the pairing experience and the permission prompt, not the device's internal security, and you must add a Bluetooth usage string or iOS will block the scan.

Want a clean Bluetooth pairing screen for your iOS app without guessing at the flow? The short answer: build it as a visible state machine. Scanning, found, connecting, connected, failed. The UI lists nearby devices live, the user taps one, and each state is shown honestly. You build the screen from a free VP0 design, the free iOS design library for AI builders, and drive it with Core Bluetooth. The honest part to keep in mind: you own the pairing experience, not the device's internal security.

## Who this is for

This is for builders connecting an iOS app to a BLE accessory, a fitness sensor, a smart-home gadget, a custom hardware product, who want a trustworthy pairing screen and need to know where the app's responsibility starts and stops.

## The pairing flow and its states

Pairing is one of the clearest examples of a state machine in app UI, so build it that way. The screen starts scanning and shows a spinner. As devices appear it lists them live, each row a discovered peripheral. The user taps one, the row moves to connecting, and on success it becomes connected with a clear confirmation. If it fails or the device goes out of range, that is its own visible state with a retry, not a frozen list. Apple's [Core Bluetooth](https://developer.apple.com/documentation/corebluetooth) framework, driven by [CBCentralManager](https://developer.apple.com/documentation/corebluetooth/cbcentralmanager), gives you the events behind each transition.

| Pairing state | Core Bluetooth event | What the UI shows |
|---|---|---|
| Scanning | scanForPeripherals | A spinner and live list |
| Found | didDiscover peripheral | A tappable device row |
| Connecting | connect called | A progress state on the row |
| Connected | didConnect | A clear confirmation |
| Failed | didFailToConnect | An error state with retry |

The most common surprise is that scanning returns nothing. Usually the central manager has not reached the powered-on state yet, or the Bluetooth usage description is missing, so wait for powered-on before you scan.

## Build it free with a VP0 design

Pick a pairing or connection design from VP0, copy its link, and prompt your AI builder:

> Rebuild this VP0 device-pairing design in SwiftUI: [paste VP0 link]. Drive it with CBCentralManager, show explicit scanning, found, connecting, connected, and failed states, list discovered devices live, and only start scanning once the central manager is powered on. Remind me to add the Bluetooth usage string to Info.plist.

Connected devices are a huge market: the Internet of Things market is projected to surpass $1 trillion, per industry research, so a solid pairing screen is a real product surface. The same hardware-honesty applies in [Core NFC and Tap to Pay for AI-built apps](/blogs/corenfc-swiftui-tap-to-pay-ai-template/), and related sensor work shows up in [an equine horse-riding speed tracker](/blogs/equine-horse-riding-speed-tracker-app-template/). For the now-playing style of a connected audio device, see [an Apple Music now-playing screen clone in SwiftUI](/blogs/apple-music-playing-now-screen-clone-swiftui/), and to celebrate a successful connection, [a confetti cannon animation in SwiftUI](/blogs/confetti-cannon-swiftui-package/). To verify the whole screen against Apple's rules, run [the Human Interface Guidelines review pass](/blogs/ios-human-interface-guidelines-ai-checker/).

## Permissions and honesty

Two non-negotiables. First, iOS will not let you scan without a Bluetooth usage description in Info.plist, like [NSBluetoothAlwaysUsageDescription](https://developer.apple.com/documentation/bundleresources/information-property-list/nsbluetoothalwaysusagedescription); omit it and the scan silently fails. Second, never fake a connection or show connected before the device actually is, because pairing UX is about trust. Your job is the honest flow and the permission, while the device's own security and protocol are its responsibility.

## Common mistakes

The first mistake is scanning before the central manager is powered on, so nothing appears. The second is forgetting the Bluetooth usage string, which silently blocks the scan. The third is no failed or out-of-range state, so a dropped connection looks frozen. The fourth is faking a connected state before it is real. The fifth is paying for a pairing kit when a free VP0 design plus Core Bluetooth delivers the same flow.

A complementary source: Nielsen's [usability heuristics](https://www.nngroup.com/articles/ten-usability-heuristics/) put visibility of system status first, so always show the user what is happening.

## Key takeaways

- A pairing screen is a visible state machine: scanning, found, connecting, connected, failed.
- Drive it with CBCentralManager and wait for powered-on before scanning.
- Add the Bluetooth usage string to Info.plist or the scan silently fails.
- Never fake a connection; pairing UX is about trust.
- Build the screen free from a VP0 design and let Core Bluetooth handle the radio.

## Frequently asked questions

Where can I find a free SwiftUI Bluetooth pairing UI template? Start from a free VP0 design: pick a device-pairing layout and have Cursor or Claude Code rebuild the scan list and connection states, then drive it with Core Bluetooth.

What is the safest way to build a BLE pairing screen with Claude Code or Cursor? Design from a free VP0 layout, drive it with CBCentralManager, add the Bluetooth usage description, show honest states, and never fake a connection.

Can VP0 provide a free SwiftUI or React Native template for device pairing? Yes. VP0 is a free iOS design library; pick a pairing design and your AI tool rebuilds the scan list and connection states at no cost.

Why does my Bluetooth scan return nothing on iOS? Usually the Bluetooth usage description is missing from Info.plist or the central manager started scanning before reaching the powered-on state. Add the string and wait for powered-on.

## Frequently asked questions

### Where can I find a free SwiftUI Bluetooth pairing UI template?

Start from a free VP0 design. VP0 is the free iOS design library for AI builders: pick a device-pairing or connection design, copy its link, and have Cursor or Claude Code rebuild the scanning list, the device rows, and the connecting and connected states, then drive it with Core Bluetooth.

### What is the safest way to build a BLE pairing screen with Claude Code or Cursor?

Design from a free VP0 layout, drive it with CBCentralManager, and add the Bluetooth usage description to Info.plist so iOS allows the scan. Show honest states, never fake a connection, and handle the failed and out-of-range cases explicitly.

### Can VP0 provide a free SwiftUI or React Native template for device pairing?

Yes. VP0 is a free iOS design library; pick a pairing or connection design and your AI tool rebuilds the scan list and connection states at no cost while Core Bluetooth handles the radio.

### Why does my Bluetooth scan return nothing on iOS?

Most often because the Bluetooth usage description is missing from Info.plist, so iOS silently blocks the scan, or because the central manager started scanning before it reached the powered-on state. Add the usage string and wait for the powered-on state before scanning.

---
*Published on the [VP0 Journal](https://vp0.com/blogs). Free to read, index and cite with attribution.*
