EASession(accessory:forProtocol:) always returns nil — MFI accessory iAP2
Platform: iOS 17+ | Hardware: Custom MFI-certified accessory (USB-C, iAP2) | Language: Swift
Problem
We have a custom MFI-certified accessory communicating over USB-C using ExternalAccessory. The app calls EASession(accessory:forProtocol:) after receiving EAAccessoryDidConnect but it always returns nil. We
never get past session creation.
What we have verified
We captured a sysdiagnose on-device and analysed the accessoryd-packets log. The full iAP2 handshake completes successfully at the OS level:
USB attach succeeds
MFI auth certificate is present and Apple-issued
Auth challenge and response complete successfully
IdentificationInformation is accepted by iOS — protocol string and Team ID are correct
EAAccessoryDidConnect fires as expected
iOS sends StartExternalAccessoryProtocolSession — the OS-level session is established
So the hardware, MFI auth, protocol string, and Team ID are all correct. Despite this, EASession(accessory:forProtocol:) returns nil in the app.
We also confirmed:
Protocol string in UISupportedExternalAccessoryProtocols in Info.plist matches the accessory exactly
Protocol string in code matches Info.plist
App entitlements are correctly configured
EAAccessoryManager.shared().registerForLocalNotifications() is called before connection
Current connection code
@objc private func accessoryDidConnect(_ notification: Notification) {
guard let accessory = notification.userInfo?[EAAccessoryKey] as? EAAccessory else { return }
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
self.tryConnectToAccessory()
}
}
private func tryConnectToAccessory() {
DispatchQueue.main.asyncAfter(deadline: .now() + 3.0) {
for accessory in EAAccessoryManager.shared().connectedAccessories {
let session = EASession(accessory: accessory, forProtocol: "")
// session is always nil here
}
}
}
Questions
The packet log shows a ~4 second gap between EAAccessoryDidConnect firing and iOS internally completing session readiness (StartExternalAccessoryProtocolSession). Is there a reliable way to know when iOS
Is it actually ready to grant an EASession, rather than using a fixed delay?
Is there a delegate callback or notification that fires when the accessory protocol session is ready to be opened, rather than relying on EAAccessoryDidConnect + an arbitrary delay?
Are there any known conditions on iOS 17+ under which EASession returns nil even though the iAP2 handshake completed successfully at the OS level?
Is retrying EASession after a nil result a supported pattern, or does a nil result mean the session will never succeed for that connection?
Any guidance appreciated.
Selecting any option will automatically load the page