tosa
tosa

Reputation: 421

OSX Cocoa Core-Bluetooth delegate and UI update thread safety

I have the OSX BLE heartrate example from: https://developer.apple.com/library/mac/samplecode/HeartRateMonitor/Introduction/Intro.html. This example updates the heartrate via binding the NSTextField to the heartRate property. heartRate is updated in peripheral:didUpdateValueForCharacteristic, which updates the bound NSTextView accordingly. Isn't peripheral:didUpdateValueForCharacteristic on another thread, but this works fine since the control's update is handled 'behind the scenes' by Cocoa?

I added another NSTextView to which I created an outlet ivar. This ivar also gets updated in peripheral:didUpdateValueForCharacteristic and [txtfldHR setIntegerValue:bpm]; is called. This also seems to work properly. But isn't updating the NSTextField via the IBOutlet dangerous (or shouldn't work at all) from another thread? How can I updated the NSTextField via the function call safely without using bindings?

I've made a similar app in Android and there I need to pass the heartrate value via a message from the BLE callback to the UI thread in order to update the UI controls.

Upvotes: 2

Views: 734

Answers (1)

Paulw11
Paulw11

Reputation: 114866

If you look at the sample code you will see that the CBCentralManager is initialised using the following code -

manager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];

If you refer to the documentation for the queue parameter of initWithDelegate, it says -

The dispatch queue to use to dispatch the central role events. If the value is nil, the central manager dispatches central role events using the main queue.

This means that your various Bluetooth delegate events will be executed using the main queue.

If you were using a different queue for your delegate operations then you would need to explicitly dispatch UI update events on the main queue via something like dispatch_async(dispatch_get_main_queue() ^{ //code });

Upvotes: 4

Related Questions