Downside
I am integrating the Runmefit SDK into my React Native app utilizing Expo Modules API to speak with a BLE gadget. When the gadget does not ship any information (e.g., empty train historical past), my app crashes with Thread 1: EXC_BAD_ACCESS (code=1, deal with=0x0) as a result of the callback within the SDK methodology notifyRunmefit is rarely executed.
My implementation
This is how I arrange the Bluetooth delegate and name the SDK methodology:
// Arrange the peripheral delegate
public func centralManager(_ central: CBCentralManager, didConnect peripheral: CBPeripheral) {
print("Linked to (peripheral.identify ?? "unknown gadget")")
self.peripheral = peripheral
peripheral.delegate = self // Setting the delegate right here
peripheral.discoverServices([CBUUID(string: UUID_Service)])
}
// Dealing with found service and traits
public func peripheral(_ peripheral: CBPeripheral, didDiscoverServices error: Error?) {
guard let companies = peripheral.companies else { return }
for service in companies {
peripheral.discoverCharacteristics([CBUUID(string: UUID_Write_Char), CBUUID(string: UUID_Notify_Char)], for: service)
}
}
public func peripheral(_ peripheral: CBPeripheral, didDiscoverCharacteristicsFor service: CBService, error: Error?) {
guard let traits = service.traits else { return }
for attribute in traits {
if attribute.uuid.uuidString == UUID_Write_Char {
self.writeCharacter = attribute
} else if attribute.uuid.uuidString == UUID_Notify_Char {
peripheral.setNotifyValue(true, for: attribute)
}
}
}
// Downside happens on this delegate methodology
public func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor attribute: CBCharacteristic, error: Error?) {
print("Acquired: (String(describing: attribute.worth))")
guard let writeCharacter = writeCharacter else {
print("No write attribute discovered")
return
}
let nsError = error as NSError? ?? NSError(area: "", code: 0, userInfo: nil)
STBlueToothData.sharedInstance().notifyRunmefit(
peripheral,
writeCharacter: writeCharacter,
attribute: attribute,
error: nsError,
full: { (error, revType, errorType, responseObject) in
// This code is rarely executed when no information is accessible
// Resulting in EXC_BAD_ACCESS crash
let nsError = error as NSError
if nsError.code != 0 {
print("Error: (error)")
} else {
let dict: [String: Any] = [
ST_RevType_Key: NSNumber(value: revType.rawValue),
ST_ErrorType_Key: NSNumber(value: errorType.rawValue)
]
NotificationCenter.default.publish(
identify: NSNotification.Title(Nof_Revice_Data_Key),
object: responseObject,
userInfo: dict
)
}
}
)
}
SDK Technique Definition
-(void)notifyRunmefit:(CBPeripheral *)peripheral
WriteCharacter:(CBCharacteristic *)writeCharacter
Attribute:(CBCharacteristic *)attribute
Error:(NSError *)error
Full:(void(^)(NSError *error, REV_TYPE revType, ERROR_TYPE errorType, id responseObject))full;
What I’ve noticed
The app works usually when the gadget sends information
When no information is accessible (e.g., empty train historical past), the app crashes with Thread 1: EXC_BAD_ACCESS (code=1, deal with=0x0)
The callback is rarely executed on this case – not even with an error
The SDK demo code does not appear to implement any safety in opposition to this state of affairs
What I’ve tried:
- Including null checks for almost every little thing
- Making an attempt to interchange the SDK name with a direct implementation
Query:
How can I modify my Swift implementation to forestall crashes when the SDK callback is not executed as a consequence of lacking information? Is there a approach to implement a timeout or fallback resolution to deal with this gracefully?