ios - React Native Module 中的 EADemo 从未接收到委托(delegate)方法 handleEvent NSStreamEventOpenCompleted?

标签 ios objective-c bluetooth react-native

我希望我有一个 react native bridge module 、线程、委托(delegate)或我不理解的生命周期问题阻止接收委托(delegate)方法调用。

我是否需要更改 NSStream scheduleInRunLoop 方法?

我正在尝试实现 react native iOS bridge module连接蓝牙“经典”(不是 BLE)External Accessory基于 Apple's EADemo example . EADemo 可以独立运行。

当我调用 EADSessionController openSession从 react native bridge 方法中,handleEvent 方法从未被调用?

我希望 handleEventinputStreamoutputStream 接收一个 NSStreamEventOpenCompleted 事件。但是收到零事件。

文件:index.js

'use strict';
var RNBluetooth = require('react-native').NativeModules.RNBluetooth;
var Bluetooth = {
  connectTo(accessory, result) {
    RNBluetooth.connectTo(accessory, result);
  },
  };
  module.exports = Bluetooth;

文件: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]);
}

文件:EADSessionController.m

#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

非常感谢任何提示或建议。

最佳答案

已解决。

将此添加到 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();
}

参见 Native Modules 下的线程部分

现在 EADSessionController.m来自 the EADemo example可以毫无问题地从 React Native Bridge 模块调用。

关于ios - React Native Module 中的 EADemo 从未接收到委托(delegate)方法 handleEvent NSStreamEventOpenCompleted?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36747333/

相关文章:

ios - 自定义 uitextfield 的保留周期(强引用)修复?

iphone - iOS - UIScrollView 不更新其内容,一些 UIViews 在重新加载后消失

bluetooth - OpenSUSE 15.0 LEAPpulseaudio无法检测到蓝牙扬声器

android - 蓝牙、wifi 和铃声模式的广播 Intent

ios - NSTimer 启动后如何更改显示的时间格式?

objective-c - 我可以通过映射模型从 CoreData 中的关系中删除对象吗?

ios - 在 Xcode 中检索当前 iCloud 帐户信息

ios - iOS/Objective-C:将自定义对象的NSArray转换为JSON

ios - UITableViewCell 自动布局宽度不适用于 UIBezierPath

linux - BlueZ 中连接和配对的区别