◉RORK LABJP
●GPT-6.1 SOL — Added to Rork's model menu (09-29) with Low, Medium and High effort; included on Pro and Max●SONNET 5.5 — Claude Sonnet 5.5 is selectable: strong at UI design and faster than Sonnet 5 (09-28)●SDK 58 — Beta since 09/15 with no stable date yet; running projects in Expo Go has required login since 09/03●WIDGET — A write-up traces an iOS widget that renders black only in production builds●OBSERVE — EAS Observe now records native crashes too (SDK 57.0.21 or later, 10/07)●NEW — My App Open Ad Only Showed When the App…●GPT-6.1 SOL — Added to Rork's model menu (09-29) with Low, Medium and High effort; included on Pro and Max●SONNET 5.5 — Claude Sonnet 5.5 is selectable: strong at UI design and faster than Sonnet 5 (09-28)●SDK 58 — Beta since 09/15 with no stable date yet; running projects in Expo Go has required login since 09/03●WIDGET — A write-up traces an iOS widget that renders black only in production builds●OBSERVE — EAS Observe now records native crashes too (SDK 57.0.21 or later, 10/07)●NEW — My App Open Ad Only Showed When the App…
Articles/App Dev
◇ App Dev/2026-06-30Intermediate

Building a Native Bluetooth Pairing Sheet with AccessorySetupKit

iOS 18's AccessorySetupKit lets you pair a single, specific device through a system sheet without the broad Bluetooth permission prompt. Assuming the native Swift that Rork Max generates, here is the path from declaration to picker to connection, with working code.

AccessorySetupKitBluetoothiOS 184Rork Max236CoreBluetooth

✦ Premium Article

Trying to connect a peripheral from my own app, the broad "App Name would like to use Bluetooth" dialog would pop up right at launch — and for a while I buried the connect feature deep in a settings screen just to avoid it. As an indie developer running utility apps on the App Store for years, I know a wide permission request in the first few seconds cools the whole experience down.

iOS 18's AccessorySetupKit changes that premise. Instead of asking for access to all of Bluetooth, your app lets the user pick just the target device inside a system-drawn sheet. Only the chosen device is authorized, and the broad permission dialog never appears. Assuming the native Swift Rork Max generates, we will walk from declaration to picker to connection. (This feature requires a native implementation; plain React Native cannot do it.)

Why you avoid asking for "everything"

Classic CoreBluetooth asks for Bluetooth permission the moment you start scanning — from the user's view, a broad "can this app see nearby devices?" grant. AccessorySetupKit inverts this: it narrows the unit of permission down to this one device.

The user picks the nearby target inside a system sheet. Your app receives the identifier of the chosen device and can connect to that device only. You never ask for a broad scan permission, so the first experience stays intact — which matters most when, like an indie developer, you are building trust from scratch.

The required declarations (Info.plist)

First declare "what kind of device you handle" in Info.plist. Miss this and the picker is silently empty.

<key>NSAccessorySetupKitSupports</key>
<array>
  <string>Bluetooth</string>
</array>
<key>NSAccessorySetupBluetoothServices</key>
<array>
  <!-- List every service UUID your device advertises -->
  <string>0000FE2C-0000-1000-8000-00805F9B34FB</string>
</array>

Even in a Rork Max project, add these two keys to the native Info.plist. List every service UUID the target advertises under NSAccessorySetupBluetoothServices; devices whose UUID is missing here never appear in the sheet.

✦

Thank you for reading this far.

Continue Reading

What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.

WHAT YOU'LL LEARN
✦A system picker that surfaces only your specific device, built with ASAccessorySession and ASDiscoveryDescriptor (working Swift)
✦How to avoid the broad Bluetooth permission dialog and still connect via CoreBluetooth without a prompt afterward
✦Info.plist NSAccessorySetupKitSupports / service-UUID declarations and how to handle added / renamed / removed events
Secure payment via Stripe · Cancel anytime
✦

Unlock This Article

Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.

or
Unlock all articles with Membership →
Share

Thank You for Reading

Rork Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • ✦Copy-paste ready implementation code
  • ✦New advanced guides published daily
  • ✦$5/mo or $10 for lifetime access
View Membership →

Related Articles

◇ App Dev2026-10-15
My Ads Never Came Back After a Subscription Expired: Fixing the Direction of an Ad-Free Check
An ad-free flag stayed on after the subscription expired because the check pointed the wrong way. Here is how I rebuilt it to wait for two purchase queries, decide only from confirmed facts, and keep the last value on failure.
◇ App Dev2026-10-15
When adjustsFontSizeToFit Shrinks Just One Row, Suspect the Box Height, Not the String
Only the 10th row of a list drops to 4pt on iOS, though the data and strings are fine. I read the Yoga rounding and font-fit sources, then counted how often the box comes up short in Node.
◇ App Dev2026-10-15
When Only EAS Build Fails with "No matching variant", Check Your Local android/build First
Gradle passes on your machine, but the Android build on EAS stops at "No matching variant of project". Reading the reports on GitHub, I traced how a Windows-generated autolinking cache can reach the Linux builder, and wrote a small script that checks for it before you queue a build.