Turns out the issue was that characteristics on the peripheral side were not configured to require encryption. They were set with "READ", "NOTIFY" and "WRITE_WITHOUT_RESPONSE" flags, which indicate that no pairing is required to use them.
To ensure that first time connection works fine between peripheral and iOS and that pairing is successful before reading from or writing to Bluetooth characteristics, ensure that they are set to require encryption: "ENCRYPT-READ", "ENCRYPT-NOTIFY" or "ENCRYPT-WRITE" (might be with a response). This is the only way that makes iOS wait for pairing before using characteristics.
After read or write from characteristics that requires encryption, Core Bluetooth waits for pairing completion before it calls its delegate methods. If pairing is cancelled, the connection is terminated. If timeout is reached (the user does not take any action on the prompt), you should receive an error:
Error Domain=CBATTErrorDomain Code=15 "Encryption is insufficient." UserInfo={NSLocalizedDescription=Encryption is insufficient.}
Topic:
App & System Services
SubTopic:
Core OS
Tags: