6

The input and output streams get opened all the time and the respective delegate methods get called with the correct NSStreamEvent code (NSStreamEventOpenCompleted). However, on some openSession attempts the streams get opened successfully but they don't work. Sometimes I can only write to the output stream but I can't read from the input stream. Sometimes I can't read or write.

Has anyone has ever ran into this problem or have any idea to why this is happening? Any help is appreciated. Thanks.

Here is some relevant code

- (BOOL)openSession
{
    _session = [[EASession alloc] initWithAccessory:_selectedAccessory
                                        forProtocol:_protocolString];

    if (!_session)
        return false;

    [_selectedAccessory setDelegate:self];
    [[_session inputStream] setDelegate:self];
    [[_session outputStream] setDelegate:self];

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^ {

        [[_session inputStream] scheduleInRunLoop:[NSRunLoop currentRunLoop]
                                          forMode:NSDefaultRunLoopMode];
        [[_session inputStream] open];

        [[_session outputStream] scheduleInRunLoop:[NSRunLoop currentRunLoop]
                                           forMode:NSDefaultRunLoopMode];
        [[_session outputStream] open];

        [[NSRunLoop currentRunLoop] run];
    });

    return true;
}

- (void)setupControllerForAccessory:(EAAccessory *)accessory withProtocolString:(NSString *)protocolString
{
    _selectedAccessory = accessory;
    _protocolString = [protocolString copy];
}

/**
 * There is something weird happening here too, this always get called twice when an accessory
 * gets connected. Once without a protocol string and once with a protocol string. I just
 * ignore the one without a protocol string.
 */
- (void)accessoryConnected:(NSNotification *)notification
{
    EAAccessory *connectedEA = [notification.userInfo objectForKey:@"EAAccessoryKey"];

    // Check to see if the connected EA has a protocol string
    if ([[connectedEA protocolStrings] count] == 0)
        return;

    [self setupControllerForAccessory:connectedEA
                   withProtocolString:[[connectedEA protocolStrings] objectAtIndex:0]];
    [self openSession];
}

- (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode
{
    switch (eventCode) {
        case NSStreamEventOpenCompleted:
            // This case always gets called twice, once for input and once for output
            NSLog(@"stream %@ opened", aStream);
            break;
        case NSStreamEventHasBytesAvailable:
            break;
        case NSStreamEventHasSpaceAvailable:
            break;
        case NSStreamEventErrorOccurred:
            break;
        case NSStreamEventEndEncountered:
            [self closeSession];
            break;
        default:
            break;
    }
}

- (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 = nil;
    _selectedAccessory = nil;
    _protocolString = nil;
}
jason
  • 134
  • 1
  • 4
  • Have you tried dispatching to the mainQueue instead of the global? – Putz1103 Mar 04 '14 at 17:40
  • I've tried dispatch_get_main_queue() as well. Same issue occurs, sometimes it fails 9 times in a row, sometimes it works 9 times in a row. – jason Mar 04 '14 at 17:56
  • When do you try to use these streams in code? Since it's dispatch you could be using the streams before the open is complete. – Putz1103 Mar 04 '14 at 18:02
  • I start writing to the stream after they successfully open (I find this out via the NSStreamEventOpenCompleted eventCode in the delegate method). However, the bluetooth device I am talking with start streaming (constant flow) data to the phone upon connection. – jason Mar 04 '14 at 18:20
  • What type of hardware are you using? Are you using BT or Hardware port? – imcc Mar 25 '14 at 00:23

1 Answers1

0

I cannot add a comment to your question(less points!) but i have some hint because my team is also facing the same problem which is intermittent using streams. We have raised a bug to the network team for the same. If possible try to log error, most probably you will getting an error "Stream ended Unexpectedly" in your debugger console. This may appear or may not appear.

Here is the similar code provided in apple documentation which is also having the same issue. https://developer.apple.com/library/ios/samplecode/SimpleURLConnections/Listings/PostController_m.html#//apple_ref/doc/uid/DTS40009245-PostController_m-DontLinkElementID_12

  • This error has stopped creeping up on me since we switched to another bluetooth module. That might have been the problem? Cannot be 100% sure.. Thanks – jason Mar 31 '14 at 04:23
  • @jason, I am facing the same problem. Could you let me know what another bluetooth module did you switch to? – ttotto Sep 03 '14 at 03:54
  • @ttotto I am using ST's bluetooth module – jason Sep 04 '14 at 20:58
  • @jason. Could you let me know any links or references about ST's bluetooth module? – ttotto Sep 05 '14 at 00:55
  • @jason,Could you let me know any links or references about ST's bluetooth module? – ttotto Sep 18 '14 at 00:31