Программа сбоя NSStreams!

Все,

Я довел его до этого момента с помощью комментариев, точек останова и т. д. Программа вылетает на отмеченном коде.

-(void) initNetworkCommunication
{
    CFReadStreamRef readStream;
    CFWriteStreamRef writeStream;
    CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)@"192.168.17.1", 2004, &readStream, &writeStream);

    inputStream = (NSInputStream *)readStream;
    outputStream = (NSOutputStream *)writeStream;
    [inputStream setDelegate:self];
    [outputStream setDelegate:self];
    [inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    [outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];

    [inputStream open];//WHY MUST YOU CRASH HERE
    [outputStream open];//WHY MUST YOU CRASH HERE ALSO!!?!?

    NSLog(@"She be opened, sir!");
}

Он не падает, если я закомментирую оба из них, но он падает, если я закомментирую любой из них (то есть они оба вызывают сбой программы). В отладчике также нет никакой информации. Все, что он делает, это отправляет меня на main.m и показывает мне

"Поток 1: программа получила сигнал: "EXC_BAD_ACCESS".

Спасибо за помощь в продвижении!

Редактировать: вот мой метод делегата, но он даже не отображает вторую активную строку в журнале.

- (void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent {

    NSLog(@"stream event %i", streamEvent); //this doesn't post in the log when stream opened...

    switch (streamEvent) {

        case NSStreamEventOpenCompleted:
            NSLog(@"Stream opened");
            break;
        case NSStreamEventHasBytesAvailable:

            if (theStream == inputStream) {

                uint8_t buffer[1024];
                int len;

                while ([inputStream hasBytesAvailable]) {
                    len = [inputStream read:buffer maxLength:sizeof(buffer)];
                    if (len > 0) {

                        NSString *output = [[NSString alloc] initWithBytes:buffer length:len encoding:NSASCIIStringEncoding];

                        if (nil != output) {

                            NSLog(@"server said: %@", output);
                            //[self messageReceived:output];

                        }
                    }
                }
            }
            break;


        case NSStreamEventErrorOccurred:

            NSLog(@"Can not connect to the host!");
            break;

        case NSStreamEventEndEncountered:

            [theStream close];
            [theStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
            //[theStream release];
            theStream = nil;

            break;
        default:
            NSLog(@"Unknown event");
    }

} 

person Baub    schedule 13.07.2011    source источник
comment
Тема 1 не является основной. Вероятно, он используется потоками, когда они открываются. Сбой может происходить в методе stream:handleEvent: вашего делегата, поэтому я предлагаю начать с него.   -  person ughoavgfhw    schedule 14.07.2011
comment
Если есть сбой, есть обратная трасса. Разместите это.   -  person bbum    schedule 15.07.2011


Ответы (5)


Происходит то, что экземпляр класса делегата освобождается (вызывая EXC_BAD_ACCESS в цикле выполнения) либо потому, что вы его не сохранили, либо вы используете ARC (весьма вероятно), и у вас нет ссылки на него.

Решение состоит в том, чтобы либо сохранить вызов класса делегата, примерно так:

SomeStreamDelegate *theDelegate = [[SomeStreamDelegate alloc] init];
[theDelegate retain];

Или, если у вас включен ARC, создайте переменную экземпляра в классе, где вы выделяете делегата, и сохраните там свой экземпляр соединения. Таким образом, ARC не освободит его, потому что экземпляр var считается ссылкой.

person arjunyg    schedule 27.05.2013

Если вы используете ARC, транслируйте потоки следующим образом:

inputStream = (__bridge NSInputStream *)readStream;
outputStream = (__bridge NSOutputStream *)writeStream;

Это должно предотвратить сбой. И имейте в виду, что если ваши потоки принадлежат отдельному потоку, а не основному потоку, это означает, что цикл выполнения необходимо вызывать вручную с помощью метода запуска после открытия потоков.

person Anand    schedule 27.02.2014
comment
Это лучший и более точный ответ - person xaphod; 19.04.2016

Когда я поместил это в свой контроллер представления (а не в отдельный класс), он работал отлично.

person Baub    schedule 18.07.2011
comment
это означает, что локальный объект не может быть сохранен. Кроме переноса всего этого в UIVIewController, вы можете указать локальный объект как iVar или свойство контроллера представления, сделав это, мне удалось вытащить из машин :) - person Ratul Sharker; 11.04.2016

У меня была аналогичная проблема, когда мое приложение вылетало из-за обратного вызова -handleEvent с огромным номером streamEvent. Я решил эту проблему, убедившись, что инициализирую объекты NSStream (входные и выходные) И открываю соединение с сервером в методе -init объекта NetworkClient, который мой VC планирует использовать.

person Sai Ramachandran    schedule 06.04.2013

Попробуйте это один раз,

NSInputStream * inputStream = objc_unretainedObject (readStream);

Может быть проблема приведения

person Futur    schedule 14.07.2011
comment
Если бы ARC был включен, этот код все равно не скомпилировался бы так, как он написан. Этот ответ не имеет смысла. - person bbum; 15.07.2011
comment
упс....может быть, я полностью мысленно просматривал потоки ios5.. Я не совсем добавил это: если приложение находится в ios5, то ‹Ответ›.. мой плохой.. как сказал bbum, это применимо только в автоматическом окружение с подсчетом ссылок.. - person Futur; 18.07.2011