I’ve run several tests to verify this issue before filing a bug report. I would appreciate your advice.
Key facts about my Bluetooth accessory:
It is not paired with system Bluetooth.
I only persist its peripheralIdentifier and bluetoothServiceUUID for later accessory migration.
Reproduction steps (intermittent)
Launch the app while applicationState is .active. Call showPicker with ASMigrationDisplayItem, migration succeeds.
Delete and reinstall the app, then repeat step 1. It fails probabilistically. Once it fails, all subsequent showPicker calls keep failing.
Rebooting the iPhone restores normal behavior.
Failure can also occur on the very first step‑1 attempt.
Additional observations from testing
When using ASMigrationDisplayItem, the picker UI never appears, whether the call succeeds or fails.
Intermittent error observed: XPC connection invalid.
After the first failure, both ASPickerDisplayItem and ASMigrationDisplayItem showPicker calls consistently fail with:
Picker already activated
Error Domain=ASErrorDomain Code=500 "(null)"
Only an iPhone reboot can recover from this broken state.
Sample demo code
import UIKit
import CoreBluetooth
import AccessorySetupKit
public class BluetoothService {
public static let share = BluetoothService()
private var session: Any?
private let image: UIImage = UIImage(systemName: "lanyardcard") ?? UIImage()
public func activeSession() {
if #available(iOS 18.4, *) {
let session = ASAccessorySession()
self.session = session
session.activate(on: .main) { [weak self] event in
guard let self = self else { return }
self.handleASKSessionEvent(event)
}
}
}
@available(iOS 18.4, *)
private func handleASKSessionEvent(_ event: ASAccessoryEvent) {
switch event.eventType {
case .activated:
self.migration()
break
default:
break
}
}
@available(iOS 18.4, *)
public func migration() {
guard UIApplication.shared.applicationState == .active else {
return
}
guard let session = self.session as? ASAccessorySession else { return }
let name = "My-DeVice-A"
let identifier = "C4B8F5B1-B37B-2B08-AAC5-BF48EF2DCB44"
let descriptor = ASDiscoveryDescriptor()
descriptor.bluetoothServiceUUID = CBUUID(string: "1234")
descriptor.bluetoothNameSubstring = name
let migration = ASMigrationDisplayItem(
name: name,
productImage: image,
descriptor: descriptor
)
migration.peripheralIdentifier = UUID(uuidString: identifier)
session.showPicker(for: [migration]) { error in
if let error = error {
print("showPicker error: \(error)")
} else {
print("showPicker success")
}
}
}
@available(iOS 18.4, *)
public func showPicker() {
guard UIApplication.shared.applicationState == .active else {
return
}
guard let session = self.session as? ASAccessorySession else { return }
let name = "My-DeVice-B"
let descriptor = ASDiscoveryDescriptor()
descriptor.bluetoothServiceUUID = CBUUID(string: "1234")
descriptor.bluetoothNameSubstring = name
let displayItem = ASPickerDisplayItem(
name: name,
productImage: image,
descriptor: descriptor
)
session.showPicker(for: [displayItem]) { error in
if let error = error {
print("showPicker error: \(error)")
} else {
print("showPicker success")
}
}
}
}
I’m looking forward to any suggestions to resolve this issue.
Topic:
App & System Services
SubTopic:
Hardware
Tags: