Не удается получить события NSInputStream в OCUnitTest - PullRequest
1 голос
/ 16 июля 2010

Я пытаюсь узнать, как использовать класс NSInputStream на iPhone с помощью модульного теста. Я могу заставить NSStream читать данные из файла, используя метод опроса, но по какой-то причине метод делегата / события не работает.

Я разместил соответствующий код ниже. Пожалуйста, игнорируйте ошибки утечки памяти и тому подобное, так как я просто пытаюсь убедиться, что знаю, как использовать класс NSStream в изолированной среде, прежде чем включать его в мой более крупный проект.

Мне интересно, может быть, я что-то упускаю из-за того, как работают циклы выполнения?

Это логический тест, который создает класс стримера для чтения из файла.

#import "StreamingTests.h"
#import "Streamer.h"

@implementation StreamingTests

- (void) testStream {
    NSLog(@"Starting stream test.");
    Streamer * streamer = [[Streamer alloc] init];

    streamer.usePolling = NO;
    streamer.readingStream = YES;
    NSThread * readThread = [[NSThread alloc] initWithTarget:streamer selector:@selector(startStreamRead:) object:nil];
    [readThread start];
    while(streamer.readingStream) {
        [NSThread sleepForTimeInterval:0.5];
    }
    [readThread cancel];
}

@end

Это простой вспомогательный объект теста, который читает из NSStream. Когда usePolling == YES, он считывает данные и выводит соответствующие сообщения NSLog. Однако, если usePolling == NO, функция события потока делегата никогда не вызывается.

@implementation Streamer
@synthesize readingStream, usePolling;

- (void) startStreamRead:(NSObject*) context {  
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
    NSLog(@"starting stream read.");
    readingStream = YES;
    /*
     NSURL * url = [NSURL URLWithString:@"http://www.google.com"];
     NSLog(@"Loading: %@",[url description]);
     NSInputStream * inStream = [[NSInputStream alloc] initWithURL:url];
     */
    NSInputStream * inStream = [[NSInputStream alloc] initWithFileAtPath:@"sample.ttc"];

    if(!usePolling) {

        [inStream setDelegate: self];
        [inStream scheduleInRunLoop: [NSRunLoop currentRunLoop]
                            forMode: NSDefaultRunLoopMode];


    }
    [inStream open];

    if(usePolling) {
        while(1) {
            if([inStream hasBytesAvailable]) {
                uint8_t buf[1024];
                unsigned int len = 0;
                len = [(NSInputStream *)inStream read:buf maxLength:1024];
                NSLog(@"Read: %d",len);
            }
            NSStreamStatus status = [inStream streamStatus];
            if(status != NSStreamStatusOpen && status != NSStreamStatusOpening) {
                NSLog(@"Stream not open.");
                break;
            }
        }
        readingStream = NO;

        NSStreamStatus status = [inStream streamStatus];
        NSError * error = [inStream streamError];
        NSLog(@"Status: %d Error Desc: %@ Reason: %@",(int)status,[error localizedDescription], [error localizedFailureReason]);

        [pool release];
    }

}


- (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode {
    NSMutableData * _data = nil;
    NSNumber * bytesRead = nil;
    NSLog(@"Event fired.");
    switch(eventCode) {
        case NSStreamEventHasBytesAvailable:
        {
            if(!_data) {
                _data = [[NSMutableData data] retain];
            }
            uint8_t buf[1024];
            unsigned int len = 0;
            len = [(NSInputStream *)stream read:buf maxLength:1024];
            if(len) {
                [_data appendBytes:(const void *)buf length:len];
                // bytesRead is an instance variable of type NSNumber.
                //[bytesRead setIntValue:[bytesRead intValue]+len];
                NSLog(@"Read %d bytes",len);
            } else {
                NSLog(@"no buffer!");
            }
            break;
        }
        case NSStreamEventEndEncountered:
        {
            [stream close];
            [stream removeFromRunLoop:[NSRunLoop currentRunLoop]
                              forMode:NSDefaultRunLoopMode];
            [stream release];
            stream = nil; // stream is ivar, so reinit it
            readingStream = NO;
            break;
        }
        default:
        {
            NSLog(@"Another event occurred.");
            break;
        }
            // continued ...
    }
}

@end

Заранее спасибо,

б

1 Ответ

0 голосов
/ 23 апреля 2012

Причина этого должна заключаться в том, что цикл выполнения заблокирован, поскольку выполняется модульный тест. Вы можете обратиться к документации NSRunLoop , где метод

runUntilDate:

может помочь вам запустить основной цикл выполнения в потоке выполнения модульного теста следующим образом:

[[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]];

Это позволяет циклу выполнения выполняться в течение 1 секунды, давая время для обработки части вашего файла. Следует отметить, что это не обеспечивает надежного способа для модульного тестирования (поскольку временной интервал может отличаться в зависимости от размера цикла выполнения) и может быть непригодным. Предоставляя вашему устройству интерфейс, который можно использовать для проверки состояния операции чтения входного потока (с завершенным состоянием чтения), например

-(BOOL)hasFinishedReadingFile

модульный тест может многократно выполнять цикл выполнения, пока приведенный выше метод не вернет TRUE и файл не будет прочитан полностью.

Дополнение: Этот вопрос о стековом потоке также решает проблему по-другому.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...