Ed *_*ain 3 bluetooth objective-c ios react-native
我希望我有一个本机桥接模块、线程、委托或生命周期问题,我不明白这会阻止接收委托方法调用。
我需要更改NSStream scheduleInRunLoop方法吗?
我正在尝试基于Apple 的 EADemo 示例实现一个React Native iOS 桥接模块来连接蓝牙“经典”(不是 BLE)外部附件。EADemo 独立运行良好。
当我从本机桥接方法中调用EADSessionController openSession 时,从不调用 handleEvent 方法?
我希望handleEvent为inputStream和outputStream接收NSStreamEventOpenCompleted事件。然而,接收到零事件。
文件:index.js
'use strict';
var RNBluetooth = require('react-native').NativeModules.RNBluetooth;
var Bluetooth = {
connectTo(accessory, result) {
RNBluetooth.connectTo(accessory, result);
},
};
module.exports = Bluetooth;
Run Code Online (Sandbox Code Playgroud)
文件:RNBluetooth.m
// open the external accesssory session from javascript
RCT_EXPORT_METHOD(connectTo:(NSDictionary *)accessoryProperties
callback:(RCTResponseSenderBlock)callback)
{
// findAccessory returns the EAAccessory matching the accessoryProperties
EAAccessory * accessory = [self findAccessory:accessoryProperties];
if(nil != accessory) {
NSLog(@"Connect to: {%@}", accessoryProperties[@"name"]);
NSLog(@"name: {%@}", accessory.name);
NSLog(@"serialNumber: {%@}", accessory.serialNumber);
NSLog(@"connectionID: {%d}", (int)accessory.connectionID);
}
// Singleton
EADSessionController * eaSessionController = [EADSessionController sharedController];
[eaSessionController setupControllerForAccessory:accessory
withProtocolString:accessoryProperties[@"protocolStrings"]];
[eaSessionController openSession];
NSString *dummyResponseString = @"openSession";
callback(@[dummyResponseString]);
}
Run Code Online (Sandbox Code Playgroud)
#import "EADSessionController.h"
NSString *EADSessionDataReceivedNotification = @"EADSessionDataReceivedNotification";
@implementation EADSessionController
@synthesize accessory = _accessory;
@synthesize protocolString = _protocolString;
#pragma mark Internal
#pragma mark Public Methods
+ (EADSessionController *)sharedController
{
static EADSessionController *sessionController = nil;
if (sessionController == nil) {
sessionController = [[EADSessionController alloc] init];
}
return sessionController;
}
- (void)dealloc
{
[self closeSession];
[self setupControllerForAccessory:nil withProtocolString:nil];
[super dealloc];
}
// initialize the accessory with the protocolString
- (void)setupControllerForAccessory:(EAAccessory *)accessory withProtocolString:(NSString *)protocolString
{
[_accessory release];
_accessory = [accessory retain];
[_protocolString release];
_protocolString = [protocolString copy];
}
// open a session with the accessory and set up the input and output stream on the default run loop
- (BOOL)openSession
{
[_accessory setDelegate:self];
_session = [[EASession alloc] initWithAccessory:_accessory forProtocol:_protocolString];
if (_session)
{
[[_session inputStream] setDelegate:self];
[[_session inputStream] scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[[_session inputStream] open];
[[_session outputStream] setDelegate:self];
[[_session outputStream] scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[[_session outputStream] open];
}
else
{
NSLog(@"creating session failed");
}
return (_session != nil);
}
// close the session with the accessory.
- (void)closeSession
{
[[_session inputStream] close];
[[_session inputStream] removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[[_session inputStream] setDelegate:nil];
[[_session outputStream] close];
[[_session outputStream] removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[[_session outputStream] setDelegate:nil];
[_session release];
_session = nil;
[_writeData release];
_writeData = nil;
[_readData release];
_readData = nil;
}
#pragma mark EAAccessoryDelegate
- (void)accessoryDidDisconnect:(EAAccessory *)accessory
{
// do something ...
}
#pragma mark NSStreamDelegateEventExtensions
// handleEvent never gets called when session opened from react native bridge?
//
// asynchronous NSStream handleEvent method
- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode
{
switch (eventCode) {
case NSStreamEventNone:
break;
case NSStreamEventOpenCompleted:
break;
case NSStreamEventHasBytesAvailable:
[self _readData];
break;
case NSStreamEventHasSpaceAvailable:
[self _writeData];
break;
case NSStreamEventErrorOccurred:
break;
case NSStreamEventEndEncountered:
break;
default:
break;
}
}
@end
Run Code Online (Sandbox Code Playgroud)
非常感谢任何提示或建议。
解决了。
将此添加到RNBluetooth.m
// This seems to get NSStream handleEvents and the write command
// running on the same thread with no contention problems
// writing to and reading from the write buffer
- (dispatch_queue_t)methodQueue
{
return dispatch_get_main_queue();
}
Run Code Online (Sandbox Code Playgroud)
请参阅本机模块下的线程部分
现在EADSessionController.m从该EADemo例如可以被称为从反应天然桥模块没有问题。